Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r72066 - in trunk/boost/msm: . back front/euml
From: christophe.j.henry_at_[hidden]
Date: 2011-05-21 18:16:11


Author: chenry
Date: 2011-05-21 18:16:11 EDT (Sat, 21 May 2011)
New Revision: 72066
URL: http://svn.boost.org/trac/boost/changeset/72066

Log:
added the possibility to choose when switching of active state occurs
Added:
   trunk/boost/msm/active_state_switching_policies.hpp (contents, props changed)
Text files modified:
   trunk/boost/msm/back/metafunctions.hpp | 43 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/msm/back/state_machine.hpp | 35 ++++++++++++++++++++++++++------
   trunk/boost/msm/front/euml/common.hpp | 23 +++++++++++++++++++++
   3 files changed, 94 insertions(+), 7 deletions(-)

Added: trunk/boost/msm/active_state_switching_policies.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/msm/active_state_switching_policies.hpp 2011-05-21 18:16:11 EDT (Sat, 21 May 2011)
@@ -0,0 +1,55 @@
+// Copyright 2008 Christophe Henry
+// henry UNDERSCORE christophe AT hotmail DOT com
+// This is an extended version of the state machine available in the boost::mpl library
+// Distributed under the same license as the original.
+// Copyright for the original version:
+// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
+// under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MSM_ACTIVE_STATE_SWITCHING_POLICIES_H
+#define BOOST_MSM_ACTIVE_STATE_SWITCHING_POLICIES_H
+
+namespace boost { namespace msm
+{
+// policy classes
+
+// Default: new active state set after the transition (after entry)
+struct active_state_switch_after_entry
+{
+ static int after_guard(int current_state,int){return current_state;}
+ static int after_exit(int current_state,int){return current_state;}
+ static int after_action(int current_state,int){return current_state;}
+ static int after_entry(int,int next_state){return next_state;}
+};
+
+// new state set before the transition starts
+struct active_state_switch_before_transition
+{
+ static int after_guard(int,int next_state){return next_state;}
+ static int after_exit(int,int next_state){return next_state;}
+ static int after_action(int,int next_state){return next_state;}
+ static int after_entry(int,int next_state){return next_state;}
+};
+
+// new state set after exit action completed
+struct active_state_switch_after_exit
+{
+ static int after_guard(int current_state,int){return current_state;}
+ static int after_exit(int,int next_state){return next_state;}
+ static int after_action(int,int next_state){return next_state;}
+ static int after_entry(int,int next_state){return next_state;}
+};
+
+// new state set after transition action completed
+struct active_state_switch_after_transition_action
+{
+ static int after_guard(int current_state,int){return current_state;}
+ static int after_exit(int current_state,int){return current_state;}
+ static int after_action(int,int next_state){return next_state;}
+ static int after_entry(int,int next_state){return next_state;}
+};
+
+} }//boost::msm
+#endif //BOOST_MSM_ACTIVE_STATE_SWITCHING_POLICIES_H

Modified: trunk/boost/msm/back/metafunctions.hpp
==============================================================================
--- trunk/boost/msm/back/metafunctions.hpp (original)
+++ trunk/boost/msm/back/metafunctions.hpp 2011-05-21 18:16:11 EDT (Sat, 21 May 2011)
@@ -63,6 +63,7 @@
 BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
 
 namespace boost { namespace msm { namespace back
 {
@@ -155,6 +156,35 @@
     typedef typename ::boost::mpl::first<all_state_ids>::type type;
 };
 
+template <class Fsm>
+struct get_active_state_switch_policy_helper
+{
+ typedef typename Fsm::active_state_switch_policy type;
+};
+template <class Iter>
+struct get_active_state_switch_policy_helper2
+{
+ typedef typename boost::mpl::deref<Iter>::type Fsm;
+ typedef typename Fsm::active_state_switch_policy type;
+};
+// returns the active state switching policy
+template <class Fsm>
+struct get_active_state_switch_policy
+{
+ typedef typename ::boost::mpl::find_if<
+ typename Fsm::configuration,
+ has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::type iter;
+
+ typedef typename ::boost::mpl::eval_if<
+ typename ::boost::is_same<
+ iter,
+ typename ::boost::mpl::end<typename Fsm::configuration>::type
+ >::type,
+ get_active_state_switch_policy_helper<Fsm>,
+ get_active_state_switch_policy_helper2< iter >
+ >::type type;
+};
+
 // returns the id of a given state
 template <class stt,class State>
 struct get_state_id
@@ -642,6 +672,19 @@
 };
 
 template <class StateType>
+struct is_active_state_switch_policy
+{
+ typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
+ typename StateType::configuration,
+ has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::value != 0> found;
+
+ typedef typename ::boost::mpl::or_<
+ typename has_active_state_switch_policy<StateType>::type,
+ found
+ >::type type;
+};
+
+template <class StateType>
 struct get_initial_event
 {
     typedef typename StateType::initial_event type;

Modified: trunk/boost/msm/back/state_machine.hpp
==============================================================================
--- trunk/boost/msm/back/state_machine.hpp (original)
+++ trunk/boost/msm/back/state_machine.hpp 2011-05-21 18:16:11 EDT (Sat, 21 May 2011)
@@ -47,6 +47,7 @@
 
 #include <boost/parameter.hpp>
 
+#include <boost/msm/active_state_switching_policies.hpp>
 #include <boost/msm/row_tags.hpp>
 #include <boost/msm/back/fold_to_list.hpp>
 #include <boost/msm/back/metafunctions.hpp>
@@ -172,6 +173,13 @@
     typedef typename QueueContainerPolicy::
         template In<transition_fct>::type events_queue_t;
 
+ typedef typename boost::mpl::eval_if<
+ typename is_active_state_switch_policy<Derived>::type,
+ get_active_state_switch_policy<Derived>,
+ // default
+ ::boost::mpl::identity<active_state_switch_after_entry>
+ >::type active_state_switching;
+
     typedef bool (*flag_handler)(library_sm const&);
 
     // all state machines are friend with each other to allow embedding any of them in another fsm
@@ -419,21 +427,24 @@
                 // guard rejected the event, we stay in the current one
                 return HANDLED_GUARD_REJECT;
             }
+ fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
 
             // the guard condition has already been checked
             execute_exit<current_state_type>
                 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
+ fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
 
             // then call the action method
             HandledEnum res = ROW::action_call(fsm,evt,
                              ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
                              ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
                              fsm.m_substate_list);
+ fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
 
             // and finally the entry method of the new current state
             convert_event_and_execute_entry<next_state_type,T2>
                 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
- fsm.m_states[region_index]=next_state;
+ fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
             return res;
         }
     };
@@ -495,15 +506,18 @@
                 // guard rejected the event, we stay in the current one
                 return HANDLED_GUARD_REJECT;
             }
+ fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
+
             // the guard condition has already been checked
             execute_exit<current_state_type>
                 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
+ fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
+ fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
 
             // and finally the entry method of the new current state
             convert_event_and_execute_entry<next_state_type,T2>
                 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
-
- fsm.m_states[region_index]=next_state;
+ fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
             return HANDLED_TRUE;
         }
     };
@@ -551,22 +565,25 @@
             {
                 return HANDLED_FALSE;
             }
+ fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
+
             // no need to check the guard condition
             // first call the exit method of the current state
             execute_exit<current_state_type>
                 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
+ fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
 
             // then call the action method
             HandledEnum res = ROW::action_call(fsm,evt,
                             ::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),
                             ::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),
                             fsm.m_substate_list);
+ fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
 
             // and finally the entry method of the new current state
             convert_event_and_execute_entry<next_state_type,T2>
                 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
-
- fsm.m_states[region_index]=next_state;
+ fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
             return res;
         }
     };
@@ -614,15 +631,19 @@
             {
                 return HANDLED_FALSE;
             }
+ fsm.m_states[region_index] = active_state_switching::after_guard(current_state,next_state);
+
             // first call the exit method of the current state
             execute_exit<current_state_type>
                 (::boost::fusion::at_key<current_state_type>(fsm.m_substate_list),evt,fsm);
+ fsm.m_states[region_index] = active_state_switching::after_exit(current_state,next_state);
+ fsm.m_states[region_index] = active_state_switching::after_action(current_state,next_state);
+
 
             // and finally the entry method of the new current state
             convert_event_and_execute_entry<next_state_type,T2>
                 (::boost::fusion::at_key<next_state_type>(fsm.m_substate_list),evt,fsm);
-
- fsm.m_states[region_index]=next_state;
+ fsm.m_states[region_index] = active_state_switching::after_entry(current_state,next_state);
             return HANDLED_TRUE;
         }
     };

Modified: trunk/boost/msm/front/euml/common.hpp
==============================================================================
--- trunk/boost/msm/front/euml/common.hpp (original)
+++ trunk/boost/msm/front/euml/common.hpp 2011-05-21 18:16:11 EDT (Sat, 21 May 2011)
@@ -62,6 +62,7 @@
 #include <boost/preprocessor/cat.hpp>
 
 #include <boost/msm/msm_grammar.hpp>
+#include <boost/msm/active_state_switching_policies.hpp>
 #include <boost/msm/front/functor_row.hpp>
 
 namespace proto = boost::proto;
@@ -309,6 +310,28 @@
 No_Msg_Queue const no_msg_queue=No_Msg_Queue();
 Deferred_Events const deferred_events=Deferred_Events();
 
+struct ActiveStateSwitchBeforeTransition : euml_config<ActiveStateSwitchBeforeTransition>
+{
+ typedef boost::msm::active_state_switch_before_transition active_state_switch_policy;
+ ActiveStateSwitchBeforeTransition(){}
+};
+ActiveStateSwitchBeforeTransition const switch_active_before_transition = ActiveStateSwitchBeforeTransition();
+
+struct ActiveStateSwitchAfterExit : euml_config<ActiveStateSwitchAfterExit>
+{
+ typedef boost::msm::active_state_switch_after_exit active_state_switch_policy;
+ ActiveStateSwitchAfterExit(){}
+};
+ActiveStateSwitchAfterExit const switch_active_after_exit = ActiveStateSwitchAfterExit();
+
+struct ActiveStateSwitchAfterAction : euml_config<ActiveStateSwitchAfterAction>
+{
+ typedef boost::msm::active_state_switch_after_transition_action active_state_switch_policy;
+ ActiveStateSwitchAfterAction(){}
+};
+ActiveStateSwitchAfterAction const switch_active_after_action = ActiveStateSwitchAfterAction();
+
+
 struct invalid_type{};
 struct make_invalid_type
 {


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