$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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()