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();
|
||||
}
|
||||
|
||||
55
main.cpp
55
main.cpp
@@ -20,51 +20,56 @@ enum MyEvent {
|
||||
int main(int argc, char * argv[]) {
|
||||
bool posted;
|
||||
PIStateMachine * root = new PIStateMachine("Machine");
|
||||
root->addOnFinish([] { piCout << "finish"; });
|
||||
|
||||
PIStateLambda * s1 = new PIStateLambda([] { piCout << "+ enter s1"; }, [] { piCout << "- exit s1"; }, "s1");
|
||||
PIStateLambda * s2 = new PIStateLambda([] { piCout << "+ enter s2"; }, [] { piCout << "- exit s2"; }, "s2");
|
||||
PIStateLambda * s3 = new PIStateLambda([] { piCout << "+ enter s3"; }, [] { piCout << "- exit s3"; }, "s3");
|
||||
PIStateLambda * s11 = new PIStateLambda([] { piCout << " + enter s11"; }, [] { piCout << " - exit s11"; }, "s11");
|
||||
PIStateLambda * s12 = new PIStateLambda([] { piCout << " + enter s12"; }, [] { piCout << " - exit s12"; }, "s12");
|
||||
PIStateLambda * s13 = new PIStateLambda([] { piCout << " + enter s13"; }, [] { piCout << " - exit s13"; }, "s13");
|
||||
PIStateLambda * s21 = new PIStateLambda([] { piCout << " + enter s21"; }, [] { piCout << " - exit s21"; }, "s21");
|
||||
PIStateLambda * s22 = new PIStateLambda([] { piCout << " + enter s22"; }, [] { piCout << " - exit s22"; }, "s22");
|
||||
PIStateLambda * s23 = new PIStateLambda([] { piCout << " + enter s23"; }, [] { piCout << " - exit s23"; }, "s23");
|
||||
PIStateLambda * s211 = new PIStateLambda([] { piCout << " + enter s211"; }, [] { piCout << " - exit s211"; }, "s211");
|
||||
PIStateLambda * s212 = new PIStateLambda([] { piCout << " + enter s212"; }, [] { piCout << " - exit s212"; }, "s212");
|
||||
PIStateLambda * s213 = new PIStateLambda([] { piCout << " + enter s213"; }, [] { piCout << " - exit s213"; }, "s213");
|
||||
PIStateLambda * s1 = new PIStateLambda([] { piCout << "+ enter s1"; }, [] { piCout << "- exit s1"; }, "s1");
|
||||
PIStateLambda * s2 = new PIStateLambda([] { piCout << "+ enter s2"; }, [] { piCout << "- exit s2"; }, "s2");
|
||||
PIStateLambda * s3 = new PIStateLambda([] { piCout << "+ enter s3"; }, [] { piCout << "- exit s3"; }, "s3");
|
||||
PIStateLambda * s11 = new PIStateLambda([] { piCout << " + enter s11"; }, [] { piCout << " - exit s11"; }, "s11");
|
||||
PIStateLambda * s12 = new PIStateLambda([] { piCout << " + enter s12"; }, [] { piCout << " - exit s12"; }, "s12");
|
||||
PIStateLambda * s13 = new PIStateLambda([] { piCout << " + enter s13"; }, [] { piCout << " - exit s13"; }, "s13");
|
||||
PIStateLambda * s21 = new PIStateLambda([] { piCout << " + enter s21"; }, [] { piCout << " - exit s21"; }, "s21");
|
||||
PIStateLambda * s22 = new PIStateLambda([] { piCout << " + enter s22"; }, [] { piCout << " - exit s22"; }, "s22");
|
||||
PIStateLambda * s23 = new PIStateLambda([] { piCout << " + enter s23"; }, [] { piCout << " - exit s23"; }, "s23");
|
||||
PIStateLambda * s211 = new PIStateLambda([] { piCout << " + enter s211"; }, [] { piCout << " - exit s211"; }, "s211");
|
||||
PIStateLambda * s212 = new PIStateLambda([] { piCout << " + enter s212"; }, [] { piCout << " - exit s212"; }, "s212");
|
||||
PIStateLambda * s213 = new PIStateLambda([] { piCout << " + enter s213"; }, [] { piCout << " - exit s213"; }, "s213");
|
||||
PIStateFinal * s214 = new PIStateFinal([] { piCout << " + enter s214 final"; }, "s214f");
|
||||
|
||||
root->addStates({s1, s2, s3});
|
||||
s1->addStates({s11, s12, s13});
|
||||
s2->addStates({s21, s22, s23});
|
||||
s21->addStates({s211, s212, s213});
|
||||
// root->addState(s214);
|
||||
|
||||
s2->setParallel(true);
|
||||
|
||||
root->setInitialState(s2);
|
||||
s1->setInitialState(s11);
|
||||
s2->setInitialState(s22);
|
||||
s2->setInitialState(s21);
|
||||
s21->setInitialState(s213);
|
||||
|
||||
s1->addTransition(s213, meVoid)->addAction([] { piCout << "action transition s1 -> s213"; });
|
||||
s21->addTransition(s22, meVoid)->addAction([] { piCout << "action transition s21 -> s22"; });
|
||||
s213->addTransition(s13, meVoid)->addAction([] { piCout << "action transition s21 -> s22"; });
|
||||
s3->addTransition(s212, meVoid)->addAction([] { piCout << "action transition s1 -> s213"; });
|
||||
// s2->addTransition(s3, meInt)->addGuard([](int i) { return i == 1; });
|
||||
// s3->addTransition(s1, meIntString)->addGuard([](int i, PIString str) { return i == 2 && str == "hello"; });
|
||||
|
||||
root->setInitialState(s1);
|
||||
root->start();
|
||||
piCout << "initial\n";
|
||||
root->print();
|
||||
|
||||
// piCout << root->postEvent(meVoid);
|
||||
// piCout << root->postEvent(meInt, 1);
|
||||
|
||||
piCout << "\npost event";
|
||||
posted = root->postEvent(meVoid);
|
||||
piCout << "posted" << posted << "\n";
|
||||
piCout << "initial" << root->isRunning() << "\n";
|
||||
piCout << "active atomics" << root->activeAtomics();
|
||||
root->print();
|
||||
|
||||
piCout << "\npost event";
|
||||
posted = root->postEvent(meVoid);
|
||||
piCout << "posted" << posted << "\n";
|
||||
piCout << "active atomics" << root->activeAtomics();
|
||||
root->print();
|
||||
|
||||
// piCout << "\npost event";
|
||||
// posted = root->postEvent(meVoid);
|
||||
// piCout << "posted" << posted << "\n";
|
||||
// root->print();
|
||||
|
||||
/*root->addStates({s1, s2, s3});
|
||||
root->setInitialState(s1);
|
||||
root->start();
|
||||
|
||||
Reference in New Issue
Block a user