Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r57714 - sandbox/msm/boost/msm/back
From: christophe.j.henry_at_[hidden]
Date: 2009-11-16 17:15:04


Author: chenry
Date: 2009-11-16 17:15:04 EST (Mon, 16 Nov 2009)
New Revision: 57714
URL: http://svn.boost.org/trac/boost/changeset/57714

Log:
bugfix deferred events: stack overflow when repeated deferred events.
Text files modified:
   sandbox/msm/boost/msm/back/common_types.hpp | 3 +
   sandbox/msm/boost/msm/back/state_machine.hpp | 45 +++++++++++++++++++++++----------------
   2 files changed, 28 insertions(+), 20 deletions(-)

Modified: sandbox/msm/boost/msm/back/common_types.hpp
==============================================================================
--- sandbox/msm/boost/msm/back/common_types.hpp (original)
+++ sandbox/msm/boost/msm/back/common_types.hpp 2009-11-16 17:15:04 EST (Mon, 16 Nov 2009)
@@ -22,7 +22,8 @@
 {
     HANDLED_FALSE=0,
     HANDLED_TRUE =1,
- HANDLED_GUARD_REJECT=2
+ HANDLED_GUARD_REJECT=2,
+ HANDLED_DEFERRED=4
 } HandledEnum;
 
 typedef HandledEnum execute_return;

Modified: sandbox/msm/boost/msm/back/state_machine.hpp
==============================================================================
--- sandbox/msm/boost/msm/back/state_machine.hpp (original)
+++ sandbox/msm/boost/msm/back/state_machine.hpp 2009-11-16 17:15:04 EST (Mon, 16 Nov 2009)
@@ -98,7 +98,7 @@
         execute_return ()> transition_fct;
     typedef ::boost::function<
         execute_return () > deferred_fct;
- typedef std::queue<deferred_fct > deferred_events_queue_t;
+ typedef std::deque<deferred_fct > deferred_events_queue_t;
     typedef std::queue<transition_fct > events_queue_t;
     typedef bool (*flag_handler)(library_sm&);
 
@@ -668,13 +668,13 @@
             handle_defer_helper<library_sm> defer_helper(m_deferred_events_queue);
             defer_helper.do_pre_handle_deferred();
             // process event
- bool handled = this->do_process_helper<library_sm,Event>(evt);
+ HandledEnum handled = this->do_process_helper<library_sm,Event>(evt);
             if (handled)
             {
                 ret_handled = HANDLED_TRUE;
             }
             // after handling, take care of the deferred events
- defer_helper.do_post_handle_deferred();
+ defer_helper.do_post_handle_deferred(handled);
 
             // now check if some events were generated in a transition and was not handled
             // because of another processing, and if yes, start handling them
@@ -682,7 +682,7 @@
 
             // event can be handled, processing
             // handle with lowest priority event-less transitions
- handle_eventless_transitions_helper<library_sm> eventless_helper(this,handled);
+ handle_eventless_transitions_helper<library_sm> eventless_helper(this,(handled!=HANDLED_FALSE));
             eventless_helper.process_automatic_event();
 
             return ret_handled;
@@ -809,7 +809,7 @@
      };
      public:
      // Construct with the default initial states
- state_machine<Derived,HistoryPolicy
+ state_machine<Derived,HistoryPolicy
 #ifdef BOOST_MSVC
           ,WorkaroundVC9
 #endif
@@ -830,7 +830,7 @@
          // create states
          fill_states(this);
      }
-
+
      // Construct with the default initial states and some default argument(s)
 #ifdef BOOST_MSVC
 
@@ -884,6 +884,7 @@
 
 #endif
 
+
      // assignment operator using the copy policy to decide if non_copyable, shallow or deep copying is necessary
      library_sm& operator= (library_sm const& rhs)
      {
@@ -977,13 +978,13 @@
     }
     // the following 2 functions handle the processing either with a try/catch protection or without
     template <class StateType,class EventType>
- typename ::boost::enable_if<typename is_no_exception_thrown<StateType>::type,bool >::type
+ typename ::boost::enable_if<typename is_no_exception_thrown<StateType>::type,HandledEnum >::type
         do_process_helper(EventType const& evt, ::boost::msm::back::dummy<0> = 0)
     {
         return this->do_process_event(evt);
     }
     template <class StateType,class EventType>
- typename ::boost::disable_if<typename is_no_exception_thrown<StateType>::type,bool >::type
+ typename ::boost::disable_if<typename is_no_exception_thrown<StateType>::type,HandledEnum >::type
         do_process_helper(EventType const& evt, ::boost::msm::back::dummy<1> = 0)
     {
         try
@@ -995,7 +996,7 @@
             // give a chance to the concrete state machine to handle
             this->exception_caught(evt,*this,e);
         }
- return false;
+ return HANDLED_FALSE;
     }
     // handling of deferred events
     // if none is found in the SM, take the following empty main version
@@ -1007,7 +1008,7 @@
         {
         }
 
- void do_post_handle_deferred()
+ void do_post_handle_deferred(HandledEnum)
         {
         }
     };
@@ -1021,14 +1022,20 @@
         {
             if (!events_queue.empty())
             {
- next_deferred_event = events_queue.front();
- events_queue.pop();
+ next_deferred_event = events_queue.back();
+ events_queue.pop_back();
             }
         }
 
- void do_post_handle_deferred()
+ void do_post_handle_deferred(HandledEnum handled)
         {
- if (next_deferred_event)
+ if (((handled & HANDLED_DEFERRED) == HANDLED_DEFERRED) && next_deferred_event )
+ {
+ // the event was already deferred, no reason to process another deferred event
+ events_queue.push_back(next_deferred_event);
+ return;
+ }
+ else if (next_deferred_event)
             {
                 next_deferred_event();
             }
@@ -1073,12 +1080,12 @@
 
     // minimum event processing without exceptions, queues, etc.
     template<class Event>
- bool do_process_event(Event const& evt)
+ HandledEnum do_process_event(Event const& evt)
     {
         // use this table as if it came directly from the user
         typedef dispatch_table<library_sm,complete_table,Event> table;
 
- bool handled = false;
+ HandledEnum handled = HANDLED_FALSE;
         // dispatch the event to every region
         for (int i=0; i<nr_regions::value;++i)
         {
@@ -1086,7 +1093,7 @@
                 table::instance.entries[this->m_states[i]](
                 *this, this->m_states[i], evt);
             this->m_states[i] = res.first;
- handled = (handled || res.second);
+ handled = (HandledEnum)((int)handled | (int)res.second);
         }
         // if the event has not been handled and we have orthogonal zones, then
         // generate an error on every active state
@@ -1631,7 +1638,7 @@
         Event temp (e);
         ::boost::function<execute_return () > f= ::boost::bind(pf, ::boost::ref(fsm),temp);
         fsm.post_deferred_event(f);
- return std::make_pair(state,HANDLED_TRUE);
+ return std::make_pair(state,HANDLED_DEFERRED);
     }
 
     // called for automatic events. Default address set in the dispatch_table at init
@@ -1645,7 +1652,7 @@
     // puts a deferred event in the queue
     void post_deferred_event(deferred_fct& deferred)
     {
- m_deferred_events_queue.push(deferred);
+ m_deferred_events_queue.push_front(deferred);
     }
     // removes one event from the message queue and processes it
     void process_message_queue()


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk