I finally figured out the reason of the above effect. Assume Ev1 and Ev2 are both deferred in the current state. Ev1 and Ev2 (in this order) are currently in state_machine::eventQueue_, and state_machine::process_queued_events() is invoked. If between Ev1 and Ev2 there's an event, which causes transition from the current state, then Ev1 will be processed (deferred), but Ev2 will have no chance to get processed, and thus it will remain in state_machine::eventQueue_. Now, when the current state is getting destroyed due to the transition, release_events() is invoked, and the following line puts Ev1 (which is deferred) *after* Ev2 (which is still is the eventQueue_): eventQueue_.splice( eventQueue_.end(), pFound->second ); The mechanism is clear now, but the question is whether it's a bug or a feature :). I attach a simple reproducing program (MSVC10, boost 1.44). Thanks. #include <iostream> #include <boost/statechart/asynchronous_state_machine.hpp> #include <boost/statechart/simple_state.hpp> #include <boost/statechart/event.hpp> #include <boost/statechart/transition.hpp> #include <boost/statechart/deferral.hpp> #include <boost/statechart/fifo_scheduler.hpp> #include <boost/mpl/list.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp> #include <boost/ref.hpp> using namespace boost::statechart; namespace mpl = boost::mpl; struct ev1to2 : event<ev1to2> {}; struct ev2to3 : event<ev2to3> {}; struct ev3to4_1 : event<ev3to4_1> {}; struct ev3to4_2 : event<ev3to4_2> {}; struct s1; struct s2; struct s3; struct s4_1; struct s4_2; struct fsm : asynchronous_state_machine<fsm, s1> { fsm(my_context ctx) : my_base(ctx) {} }; struct s1 : simple_state<s1, fsm> { typedef mpl::list< transition<ev1to2, s2>, deferral<ev2to3>, deferral<ev3to4_1>, deferral<ev3to4_2>
reactions; s1() { std::cout << "s1" << std::endl; } };
struct s2 : simple_state<s2, fsm> { typedef mpl::list< transition<ev2to3, s3>, deferral<ev3to4_1>, deferral<ev3to4_2>
reactions; s2() { std::cout << "s2" << std::endl; } };
struct s3 : simple_state<s3, fsm> { typedef mpl::list< transition<ev3to4_1, s4_1>, transition<ev3to4_2, s4_2>
reactions; s3() { std::cout << "s3" << std::endl; } };
struct s4_1 : simple_state<s4_1, fsm> { s4_1() { std::cout << "s4_1" << std::endl; } }; struct s4_2 : simple_state<s4_2, fsm> { s4_2() { std::cout << "s4_2" << std::endl; } }; void enqueue(fifo_scheduler<> &sched, fifo_scheduler<>::processor_handle handle) { std::cout << "e3to4_1" << std::endl; sched.queue_event(handle, new ev3to4_1); std::cout << "e2to3" << std::endl; sched.queue_event(handle, new ev2to3); std::cout << "e3to4_2" << std::endl; sched.queue_event(handle, new ev3to4_2); std::cout << "e1to2" << std::endl; sched.queue_event(handle, new ev1to2); } int main() { fifo_scheduler<> fifoSched(true); boost::thread t1(boost::bind(&fifo_scheduler<>::operator(), &fifoSched, 0)); fifo_scheduler<>::processor_handle sessionProcessor = fifoSched.create_processor<fsm>(); fifoSched.initiate_processor(sessionProcessor); boost::thread t2(enqueue, boost::ref(fifoSched), sessionProcessor); t1.join(); t2.join(); }