state machine, parallel seems to work, final state and info about active atomic states
This commit is contained in:
@@ -27,5 +27,11 @@ PIStateMachine::PIStateMachine(const PIString & n): PIStateBase(n) {
|
||||
|
||||
bool PIStateMachine::start() {
|
||||
setActiveRecursive(false);
|
||||
return PIStateBase::start();
|
||||
is_running = PIStateBase::start();
|
||||
return is_running;
|
||||
}
|
||||
|
||||
|
||||
void PIStateMachine::onFinish() {
|
||||
need_finish = true;
|
||||
}
|
||||
|
||||
@@ -39,11 +39,22 @@ public:
|
||||
PIStateMachine(const PIString & n = {});
|
||||
|
||||
bool start();
|
||||
bool isRunning() const { return is_running; }
|
||||
void addOnFinish(std::function<void()> f) { on_finish = f; }
|
||||
|
||||
template<typename... Args>
|
||||
bool postEvent(int event_id, Args... args) {
|
||||
if (!is_running) return false;
|
||||
need_finish = false;
|
||||
PIScopeExitCall exit_call([this] {
|
||||
if (need_finish) {
|
||||
is_running = false;
|
||||
if (on_finish) on_finish();
|
||||
}
|
||||
});
|
||||
PIVector<PIStateBase *> active_states;
|
||||
gatherActiveStates(active_states);
|
||||
// piCout << "active" << active_states;
|
||||
for (auto * s: active_states) {
|
||||
for (auto * t: s->transitions) {
|
||||
if (t->eventID != event_id) continue;
|
||||
@@ -55,6 +66,12 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void onFinish() override;
|
||||
|
||||
bool is_running = false, need_finish = false;
|
||||
std::function<void()> on_finish;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,23 @@ PIStateBase::~PIStateBase() {
|
||||
}
|
||||
|
||||
|
||||
PIVector<PIStateBase *> PIStateBase::activeChildren() const {
|
||||
if (!isParallel()) {
|
||||
if (active_state) return {active_state};
|
||||
return {};
|
||||
}
|
||||
if (isActive()) return children;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
PIVector<PIStateBase *> PIStateBase::activeAtomics() const {
|
||||
PIVector<PIStateBase *> ret;
|
||||
gatherActiveAtomicStates(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PIStateBase::addState(PIStateBase * s) {
|
||||
children << s;
|
||||
s->parent_state = this;
|
||||
@@ -60,7 +77,8 @@ PITransitionBase * PIStateBase::addTransition(PIStateBase * target, int event_id
|
||||
|
||||
|
||||
void PIStateBase::print(PIString prefix) {
|
||||
PICout(PICoutManipulators::AddNewLine) << prefix << "[" << (isActive() ? "*" : " ") << "] " << getName();
|
||||
PICout(PICoutManipulators::AddNewLine) << prefix << "[" << (isActive() ? "*" : " ") << "] " << getName() << " active "
|
||||
<< activeChildren();
|
||||
prefix += " ";
|
||||
for (auto * c: children)
|
||||
c->print(prefix);
|
||||
@@ -72,11 +90,19 @@ bool PIStateBase::start() {
|
||||
setActive(true);
|
||||
return true;
|
||||
} else {
|
||||
if (initial_state) {
|
||||
if (!isParallel()) {
|
||||
if (initial_state) {
|
||||
setActive(true);
|
||||
return initial_state->start();
|
||||
} else
|
||||
piCout << "error:" << getName() << "no initial state!";
|
||||
} else {
|
||||
setActive(true);
|
||||
return initial_state->start();
|
||||
} else
|
||||
piCout << "error:" << getName() << "no initial state!";
|
||||
for (auto * s: children) {
|
||||
if (!s->start()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -85,8 +111,16 @@ bool PIStateBase::start() {
|
||||
void PIStateBase::setActive(bool yes) {
|
||||
bool prev_active = is_active;
|
||||
is_active = yes;
|
||||
if (!prev_active && is_active) onEnter();
|
||||
if (prev_active && !is_active) onExit();
|
||||
if (parent_state && yes) parent_state->childActived(this);
|
||||
if (!prev_active && is_active) {
|
||||
onEnter();
|
||||
// if (isParallel()) setChildrenActive(true);
|
||||
}
|
||||
if (prev_active && !is_active) {
|
||||
active_state = nullptr;
|
||||
if (isParallel()) setChildrenActiveRecursive(false);
|
||||
onExit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,26 +132,37 @@ void PIStateBase::setActiveRecursive(bool yes) {
|
||||
}
|
||||
|
||||
|
||||
void PIStateBase::setChildActiveRecursive(bool yes) {
|
||||
void PIStateBase::setChildrenActive(bool yes) {
|
||||
for (auto * c: children)
|
||||
c->setActive(yes);
|
||||
}
|
||||
|
||||
|
||||
void PIStateBase::setChildrenActiveRecursive(bool yes) {
|
||||
for (auto * c: children)
|
||||
c->setActiveRecursive(yes);
|
||||
}
|
||||
|
||||
|
||||
void PIStateBase::setChildActive(PIStateBase * s) {
|
||||
if (isAtomic()) return;
|
||||
if (!s) s = initial_state;
|
||||
if (!s) {
|
||||
piCout << "error:" << getName() << "no initial state!";
|
||||
return;
|
||||
void PIStateBase::activeChild(PIStateBase * c) {
|
||||
setActive(true);
|
||||
if (isParallel())
|
||||
for (auto * s: children) {
|
||||
if (c != s) s->start();
|
||||
}
|
||||
else {
|
||||
if (!c) c = initial_state;
|
||||
if (c) c->setActive(true);
|
||||
}
|
||||
for (auto * c: children)
|
||||
c->setActive(false);
|
||||
if (active_state) {
|
||||
if (active_state != s) active_state->setActive(false);
|
||||
}
|
||||
active_state = s;
|
||||
if (active_state) active_state->setActive(true);
|
||||
}
|
||||
|
||||
|
||||
void PIStateBase::childActived(PIStateBase * s) {
|
||||
if (!isParallel()) {
|
||||
active_state = s;
|
||||
if (active_state->isFinal()) onFinish();
|
||||
} else
|
||||
active_state = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +181,14 @@ void PIStateBase::propagateRoot(PIStateMachine * r) {
|
||||
void PIStateBase::gatherActiveStates(PIVector<PIStateBase *> & output) {
|
||||
for (auto * c: children)
|
||||
c->gatherActiveStates(output);
|
||||
if (is_active) output << this;
|
||||
if (isActive()) output << this;
|
||||
}
|
||||
|
||||
|
||||
void PIStateBase::gatherActiveAtomicStates(PIVector<PIStateBase *> & output) const {
|
||||
for (auto * c: children)
|
||||
c->gatherActiveAtomicStates(output);
|
||||
if (isActive() && isAtomic()) output << const_cast<PIStateBase *>(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,9 +44,13 @@ public:
|
||||
|
||||
virtual void onEnter() {}
|
||||
virtual void onExit() {}
|
||||
virtual void onFinish() {}
|
||||
|
||||
PIStateMachine * machine() const { return root; }
|
||||
PIStateBase * parent() const { return parent_state; }
|
||||
PIStateBase * activeChild() const { return active_state; }
|
||||
PIVector<PIStateBase *> activeChildren() const;
|
||||
PIVector<PIStateBase *> activeAtomics() const;
|
||||
|
||||
void addState(PIStateBase * s);
|
||||
void addStates(PIVector<PIStateBase *> s);
|
||||
@@ -60,6 +64,7 @@ public:
|
||||
bool isStateMachine() const { return is_root; }
|
||||
bool isActive() const { return is_active; }
|
||||
bool isParallel() const { return is_parallel; }
|
||||
bool isFinal() const { return is_final; }
|
||||
bool isAtomic() const { return children.isEmpty(); }
|
||||
bool isCompound() const { return children.isNotEmpty(); }
|
||||
const PIVector<PIStateBase *> & getChildren() const { return children; }
|
||||
@@ -71,14 +76,17 @@ protected:
|
||||
bool start();
|
||||
void setActive(bool yes);
|
||||
void setActiveRecursive(bool yes);
|
||||
void setChildActiveRecursive(bool yes);
|
||||
void setChildActive(PIStateBase * s);
|
||||
void setChildrenActive(bool yes);
|
||||
void setChildrenActiveRecursive(bool yes);
|
||||
void activeChild(PIStateBase * c);
|
||||
void childActived(PIStateBase * s);
|
||||
void propagateRoot(PIStateMachine * r);
|
||||
void gatherActiveStates(PIVector<PIStateBase *> & output);
|
||||
void gatherActiveAtomicStates(PIVector<PIStateBase *> & output) const;
|
||||
void gatherPathToMachine(PIVector<PIStateBase *> & output);
|
||||
PIVector<PIStateBase *> pathToMachine();
|
||||
|
||||
bool is_active = false, is_root = false, is_parallel = false;
|
||||
bool is_active = false, is_root = false, is_parallel = false, is_final = false;
|
||||
PIVector<PIStateBase *> children;
|
||||
PIVector<PITransitionBase *> transitions;
|
||||
PIStateBase *active_state = nullptr, *initial_state = nullptr, *parent_state = nullptr;
|
||||
@@ -107,20 +115,26 @@ private:
|
||||
|
||||
class PIP_EXPORT PIStateFinal: public PIStateBase {
|
||||
public:
|
||||
PIStateFinal(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {}): PIStateBase(n) {
|
||||
enter = on_enter;
|
||||
exit = on_exit;
|
||||
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n) {
|
||||
is_final = true;
|
||||
enter = on_finish;
|
||||
}
|
||||
void onEnter() override {
|
||||
if (enter) enter();
|
||||
}
|
||||
void onExit() override {
|
||||
if (exit) exit();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> enter, exit;
|
||||
std::function<void()> enter;
|
||||
};
|
||||
|
||||
|
||||
inline PICout operator<<(PICout c, PIStateBase * s) {
|
||||
if (!s)
|
||||
c << "state(nullptr)";
|
||||
else
|
||||
c << ("state(" + s->getName() + ")");
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,11 +71,24 @@ void PITransitionBase::trigger() {
|
||||
target_path.remove(target_path.size_s() - common_count, common_count);
|
||||
// piCout << "source_path" << source_path;
|
||||
// piCout << "target_path" << target_path;
|
||||
source_state->setChildActiveRecursive(false);
|
||||
// piCout << "source_state before" << source_state;
|
||||
for (int i = target_path.size_s() - 1; i >= 0; --i) {
|
||||
// piCout << "check" << source_state->activeChild() << target_path[i];
|
||||
if (source_state->activeChild() == target_path[i])
|
||||
source_state = target_path[i];
|
||||
else
|
||||
break;
|
||||
}
|
||||
// piCout << "source_state after" << source_state;
|
||||
source_state->setChildrenActiveRecursive(false);
|
||||
for (auto * s: source_path)
|
||||
s->setActive(false);
|
||||
makeAction();
|
||||
for (auto * s: source_target_path)
|
||||
s->setActive(true);
|
||||
for (int i = 0; i < source_target_path.size_s(); ++i) {
|
||||
if (i == source_target_path.size_s() - 1)
|
||||
source_target_path[i]->start();
|
||||
else
|
||||
source_target_path[i]->activeChild(source_target_path[i + 1]);
|
||||
}
|
||||
if (target_state->isCompound()) target_state->start();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user