Skip to content

Commit

Permalink
Adds handling information about events added to the process_queue
Browse files Browse the repository at this point in the history
  • Loading branch information
J-Meyers authored and kris-jusiak committed May 23, 2023
1 parent ef0f2fd commit 0387da0
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 28 deletions.
9 changes: 5 additions & 4 deletions example/defer_and_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct defer_and_process {
return make_transition_table(
*"idle"_s + event<e1> / defer
, "idle"_s + event<e2> = "s1"_s
, "s1"_s + event<e1> = "s2"_s
, "s1"_s + event<e1> / process(e2{}) = "s2"_s
, "s2"_s + event<e3> / process(e4{})
, "s2"_s + event<e4> = X
);
Expand All @@ -40,12 +40,13 @@ int main() {
sm; /// defer_queue policy to enable deferred events using std::queue
assert(sm.is("idle"_s));

sm.process_event(e1{});
assert(sm.process_event(e1{}));
assert(sm.is("idle"_s));

sm.process_event(e2{}); /// triggers idle -> s1 and s1 -> s2 (via deferred e1)
assert(!sm.process_event(e2{})); /// triggers idle -> s1 and s1 -> s2 (via deferred e1)
/// additionally triggers e2 again which is unhandled so it returns false
assert(sm.is("s2"_s));

sm.process_event(e3{}); /// triggers s2.process(e4) -> X (via processed e4)
assert(sm.process_event(e3{})); /// triggers s2.process(e4) -> X (via processed e4)
assert(sm.is(sml::X));
}
11 changes: 6 additions & 5 deletions include/boost/sml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1426,13 +1426,14 @@ struct sm_impl : aux::conditional_t<aux::is_empty<typename TSM::sm>::value, aux:
const auto lock = thread_safety_.create_lock();
(void)lock;
bool handled = process_internal_events(event, deps, subs);
bool queued_handled = true;
do {
do {
while (process_internal_events(anonymous{}, deps, subs)) {
}
} while (process_defer_events(deps, subs, handled, aux::type<defer_queue_t<TEvent>>{}, events_t{}));
} while (process_queued_events(deps, subs, aux::type<process_queue_t<TEvent>>{}, events_t{}));
return handled;
} while (process_queued_events(deps, subs, queued_handled, aux::type<process_queue_t<TEvent>>{}, events_t{}));
return handled && queued_handled;
}
constexpr void initialize(const aux::type_list<> &) {}
template <class TState>
Expand Down Expand Up @@ -1639,7 +1640,7 @@ struct sm_impl : aux::conditional_t<aux::is_empty<typename TSM::sm>::value, aux:
return processed_events;
}
template <class TDeps, class TSubs, class... TEvents>
constexpr bool process_queued_events(TDeps &, TSubs &, const aux::type<no_policy> &, const aux::type_list<TEvents...> &) {
constexpr bool process_queued_events(TDeps &, TSubs &, bool &, const aux::type<no_policy> &, const aux::type_list<TEvents...> &) {
return false;
}
template <class TDeps, class TSubs, class TEvent>
Expand All @@ -1654,13 +1655,13 @@ struct sm_impl : aux::conditional_t<aux::is_empty<typename TSM::sm>::value, aux:
#endif
}
template <class TDeps, class TSubs, class TDeferQueue, class... TEvents>
bool process_queued_events(TDeps &deps, TSubs &subs, const aux::type<TDeferQueue> &, const aux::type_list<TEvents...> &) {
bool process_queued_events(TDeps &deps, TSubs &subs, bool &queued_handled, const aux::type<TDeferQueue> &, const aux::type_list<TEvents...> &) {
using dispatch_table_t = bool (sm_impl::*)(TDeps &, TSubs &, const void *);
const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(sizeof...(TEvents))] = {
&sm_impl::process_event_no_queue<TDeps, TSubs, TEvents>...};
bool wasnt_empty = !process_.empty();
while (!process_.empty()) {
(this->*dispatch_table[process_.front().id])(deps, subs, process_.front().data);
queued_handled &= (this->*dispatch_table[process_.front().id])(deps, subs, process_.front().data);
process_.pop();
}
return wasnt_empty;
Expand Down
26 changes: 13 additions & 13 deletions test/ft/actions_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,26 +85,26 @@ test process_event_from_substate = [] {
expect(sm.is(idle));
expect(sm.is<decltype(sml::state<sub>)>(s1));

sm.process_event(e1{});
expect(sm.process_event(e1{}));
expect(sm.is(sml::state<sub>));
expect(sm.is<decltype(sml::state<sub>)>(s1));
expect(!c_.a_called);

sm.process_event(e1{});
expect(sm.process_event(e1{}));
expect(sm.is(sml::state<sub>));
expect(sm.is<decltype(sml::state<sub>)>(s2));
expect(!c_.a_called);

sm.process_event(e2{}); // + process(e3{})
expect(!sm.process_event(e2{})); // + process(e3{}) + process(e2{})
expect(sm.is(sml::state<sub>));
expect(sm.is<decltype(sml::state<sub>)>(s3));
expect(!c_.a_called);

sm.process_event(e3{});
expect(sm.process_event(e3{}));
expect(sm.is(sml::state<sub>));
expect(sm.is<decltype(sml::state<sub>)>(sml::X));

sm.process_event(e4{});
expect(sm.process_event(e4{}));
expect(1 == c_.a_called);
};

Expand Down Expand Up @@ -148,7 +148,7 @@ test queue_and_internal_process_events = [] {
return make_transition_table(
* idle + on_entry<sml::initial> / process(e1())
, s1 <= idle + event<e1>
, s2 <= s1
, s2 <= s1 / process(e1()) // This process is unhandled, but the state machine still transitions to s2
, s2 + on_entry<_> / process(e2())
, s3 <= s2 + event<e2>
, X <= s3
Expand Down Expand Up @@ -186,7 +186,7 @@ test queue_process_reaction = [] {

sml::sm<c, sml::process_queue<std::queue>> sm{};

sm.process_event(e1());
expect(!sm.process_event(e1())); // e3 was unexpected so it returns false
expect(sm.is(sml::X));

const c& c_ = sm;
Expand All @@ -209,7 +209,7 @@ test mix_process_and_internal = [] {

sml::sm<c, sml::process_queue<std::queue>> sm{};

sm.process_event(e1{});
expect(sm.process_event(e1{}));
expect(sm.is(sml::X));
};

Expand Down Expand Up @@ -242,11 +242,11 @@ test process_event_sent_from_substate = [] {
expect(sm.is(idle, s2));
expect(sm.is<decltype(sml::state<sub>)>(s1));

sm.process_event(e1{});
expect(sm.process_event(e1{}));
expect(sm.is(sml::state<sub>, s2));
expect(sm.is<decltype(sml::state<sub>)>(s1));

sm.process_event(e1{}); // + process(e2{})
expect(sm.process_event(e1{})); // + process(e2{})
expect(sm.is(sml::X, sml::X));
expect(sm.is<decltype(sml::state<sub>)>(sml::X));
};
Expand Down Expand Up @@ -279,10 +279,10 @@ test process_event_of_substate = [] {
expect(sm.is(idle));
expect(sm.is<decltype(sml::state<sub>)>(s1));

sm.process_event(e1{});
expect(sm.process_event(e1{}));
expect(sm.is(sml::state<sub>));

sm.process_event(e2{}); // + process(e2{})
expect(sm.process_event(e2{})); // + process(e2{})
expect(sm.is(sml::state<sub>));
expect(sm.is<decltype(sml::state<sub>)>(sml::X));
};
Expand Down Expand Up @@ -327,7 +327,7 @@ test process_between_substates = [] {
expect(sm.is<decltype(sml::state<sub1>)>(s1));
expect(sm.is<decltype(sml::state<sub2>)>(s2));

sm.process_event(e1{});
expect(sm.process_event(e1{}));
expect(sm.is(sml::X, sml::X));
expect(sm.is<decltype(sml::state<sub1>)>(sml::X));
expect(sm.is<decltype(sml::state<sub2>)>(sml::X));
Expand Down
12 changes: 6 additions & 6 deletions test/ft/actions_process_n_defer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ test mix_process_n_defer = [] {
, s3 + event<e2> / defer = s4
, s4 + event<e2> = s5
, s5 = s6
, s6 + on_entry<_> / process(e3{})
, s6 + on_entry<_> / (process(e1{}), process(e3{})) // e1 is not handled
, s6 + event<e3> = s7
, s7 = X
);
// clang-format on
}
}; // internal, defer, process, defer, internal, process, internal
sml::sm<c, sml::process_queue<std::queue>, sml::defer_queue<std::deque>> sm{};
sm.process_event(e1{});
expect(!sm.process_event(e1{}));
expect(sm.is(sml::X));
};

Expand Down Expand Up @@ -105,10 +105,10 @@ test process_n_defer_again = [] {

std::string calls;
sml::sm<c, sml::process_queue<std::queue>, sml::defer_queue<std::deque>> sm{calls};
sm.process_event(e1{});
sm.process_event(e1{});
sm.process_event(e1{});
sm.process_event(e3{});
expect(sm.process_event(e1{}));
expect(sm.process_event(e1{}));
expect(sm.process_event(e1{}));
expect(sm.process_event(e3{}));
expect(calls == "");
sm.process_event(e2{});
std::cout << calls << "\n";
Expand Down

0 comments on commit 0387da0

Please sign in to comment.