Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50886 - in sandbox/msm: boost/msm libs/msm/doc
From: christophe.j.henry_at_[hidden]
Date: 2009-01-29 18:03:37


Author: chenry
Date: 2009-01-29 18:03:36 EST (Thu, 29 Jan 2009)
New Revision: 50886
URL: http://svn.boost.org/trac/boost/changeset/50886

Log:
- simple FSM compile with gcc 3.3
- FSMs with composites or small size compile but do not work completely (events inside a composite lead to no_transition)
- test version of visitable states added (need new policy in state_machine)
Added:
   sandbox/msm/boost/msm/visitable_policies.hpp (contents, props changed)
Text files modified:
   sandbox/msm/boost/msm/metafunctions.hpp | 5
   sandbox/msm/boost/msm/state_machine.hpp | 162 +++++++++++++++++++++++----------------
   sandbox/msm/libs/msm/doc/SM.cpp | 45 +++++++++-
   sandbox/msm/libs/msm/doc/index.html | 8 +
   4 files changed, 145 insertions(+), 75 deletions(-)

Modified: sandbox/msm/boost/msm/metafunctions.hpp
==============================================================================
--- sandbox/msm/boost/msm/metafunctions.hpp (original)
+++ sandbox/msm/boost/msm/metafunctions.hpp 2009-01-29 18:03:36 EST (Thu, 29 Jan 2009)
@@ -30,6 +30,7 @@
 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
 BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
 
 namespace boost { namespace msm
 {
@@ -178,8 +179,8 @@
 template <class State>
 struct is_composite_state
 {
- enum {value = State::is_composite_tag::value};
- typedef typename State::is_composite_tag type;
+ enum {value = has_composite_tag<State>::type::value};
+ typedef typename has_composite_tag<State>::type type;
 };
 
 // transform a transition table in a container of source states

Modified: sandbox/msm/boost/msm/state_machine.hpp
==============================================================================
--- sandbox/msm/boost/msm/state_machine.hpp (original)
+++ sandbox/msm/boost/msm/state_machine.hpp 2009-01-29 18:03:36 EST (Thu, 29 Jan 2009)
@@ -46,6 +46,7 @@
 #include <boost/msm/history_policies.hpp>
 #include <boost/msm/bind_helpers.hpp>
 #include <boost/msm/copy_policies.hpp>
+#include <boost/msm/visitable_policies.hpp>
 
 namespace mpl = boost::mpl;
 
@@ -56,7 +57,6 @@
 
 namespace boost { namespace msm
 {
-
 // the interface for all states. Defines entry and exit functions. Overwrite to implement for any state needing it.
 struct state_base
 {
@@ -67,6 +67,8 @@
 #else
     ~state_base() {}
 #endif
+ // used only in conjunction with the VisitableStates state_machine policy
+ void accept(VisitorBase&){}
     // empty implementation for the states not wishing to define an entry condition
     // will not be called polymorphic way
         template <class Event>
@@ -105,7 +107,6 @@
 struct state : public state_base, SMPtrPolicy
 {
     // tags
- typedef mpl::bool_<false> is_composite_tag;
     // default: no flag
     typedef mpl::vector<> flag_list;
     //default: no deferred events
@@ -131,7 +132,6 @@
 struct terminate_state : public state_base, SMPtrPolicy
 {
     // tags
- typedef mpl::bool_<false> is_composite_tag;
     typedef mpl::vector<boost::msm::TerminateFlag> flag_list;
     //default: no deferred events
     typedef mpl::vector<> deferred_events;
@@ -151,7 +151,6 @@
 struct interrupt_state : public state_base, SMPtrPolicy
 {
     // tags
- typedef mpl::bool_<false> is_composite_tag;
     typedef mpl::vector<boost::msm::InterruptedFlag,
                         boost::msm::EndInterruptFlag<EndInterruptEvent> >
                                                     flag_list;
@@ -193,7 +192,6 @@
     : public state_base, explicit_entry<Composite,ZoneIndex> ,SMPtrPolicy
 {
     // tags
- typedef mpl::bool_<false> is_composite_tag;
     typedef int pseudo_entry;
     // default: no flag
     typedef mpl::vector<> flag_list;
@@ -216,7 +214,6 @@
 struct exit_pseudo_state : public state_base , SMPtrPolicy
 {
     // tags
- typedef mpl::bool_<false> is_composite_tag;
     typedef int pseudo_exit;
     typedef int no_automatic_create;
     typedef Composite owner;
@@ -293,13 +290,13 @@
 };
 
 // forward declaration
-template<class Derived,class HistoryPolicy,class CopyPolicy>
+template<class Derived,class HistoryPolicy,class VisitablePolicy,class CopyPolicy>
 class state_machine;
 
 // Generates a singleton runtime lookup table that maps current state
 // to a function that makes the SM take its transition on the given
 // Event type.
-template <class Fsm, class HistoryPolicy, class CopyPolicy,class Stt, class Event>
+template <class Fsm, class HistoryPolicy,class VisitablePolicy, class CopyPolicy,class Stt, class Event>
 struct dispatch_table
 {
  private:
@@ -398,7 +395,7 @@
             {
             typedef typename create_stt<Fsm>::type stt;
             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
- cell call_no_transition = &state_machine<Fsm,HistoryPolicy,CopyPolicy>::call_no_transition;
+ cell call_no_transition = &state_machine<Fsm,HistoryPolicy,VisitablePolicy,CopyPolicy>::call_no_transition;
             tofill_entries[state_id] = call_no_transition;
             }
             template <class State>
@@ -407,7 +404,7 @@
             {
             typedef typename create_stt<Fsm>::type stt;
             BOOST_STATIC_CONSTANT(int, state_id = (get_state_id<stt,State>::value));
- cell call_no_transition = &state_machine<Fsm,HistoryPolicy,CopyPolicy>::defer_transition;
+ cell call_no_transition = &state_machine<Fsm,HistoryPolicy,VisitablePolicy,CopyPolicy>::defer_transition;
             tofill_entries[state_id] = call_no_transition;
             }
             dispatch_table* self;
@@ -470,30 +467,32 @@
 
 
 // This declares the statically-initialized dispatch_table instance.
-template <class Fsm, class HistoryPolicy, class CopyPolicy,class Stt, class Event>
-const dispatch_table<Fsm, HistoryPolicy,CopyPolicy,Stt, Event>
-dispatch_table<Fsm, HistoryPolicy,CopyPolicy,Stt, Event>::instance;
+template <class Fsm, class HistoryPolicy,class VisitablePolicy, class CopyPolicy,class Stt, class Event>
+const dispatch_table<Fsm, HistoryPolicy,VisitablePolicy,CopyPolicy,Stt, Event>
+dispatch_table<Fsm, HistoryPolicy,VisitablePolicy,CopyPolicy,Stt, Event>::instance;
 
 // CRTP base class for state machines. Pass the actual FSM class as
 // the Derived parameter.
-template<class Derived,class HistoryPolicy=NoHistory,class CopyPolicy=NoCopy>
-class state_machine : public state_base, CopyPolicy
+template<class Derived,class HistoryPolicy=NoHistory,
+ class VisitablePolicy=NotVisitableStates, class CopyPolicy=NoCopy>
+class state_machine : public state_base,public VisitablePolicy,CopyPolicy
 {
 private:
     typedef boost::function<
- execute_return ()> transition_fct;
+ execute_return ()> transition_fct;
     typedef boost::function<
- execute_return () > deferred_fct;
- typedef std::queue<deferred_fct > deferred_events_queue_t;
- typedef std::queue<transition_fct > events_queue_t;
- typedef bool (*flag_handler)(state_machine<Derived,HistoryPolicy,CopyPolicy>&);
+ execute_return () > deferred_fct;
+ typedef std::queue<deferred_fct > deferred_events_queue_t;
+ typedef std::queue<transition_fct > events_queue_t;
+ typedef bool (*flag_handler)(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>&);
 
     // all state machines are friend with each other to allow embedding any of them in another fsm
- template <class ,class ,class > friend class state_machine;
+ template <class ,class ,class,class > friend class state_machine;
 
  public:
     // tags
- typedef mpl::bool_<true> is_composite_tag;
+ typedef int composite_tag;
+
     // default: no flag
     typedef mpl::vector0<> flag_list;
     //default: no deferred events
@@ -530,7 +529,7 @@
         // extend the table with tables from composite states
         typedef typename extend_table<Derived>::type complete_table;
         // use this table as if it came directly from the user
- typedef dispatch_table<Derived,HistoryPolicy,CopyPolicy,complete_table,Event> table;
+ typedef dispatch_table<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy,complete_table,Event> table;
 
         HandledEnum ret_handled=HANDLED_FALSE;
         // if the state machine is terminated, do not handle any event
@@ -545,8 +544,8 @@
         if (m_event_processing)
         {
             // event has to be put into the queue
- execute_return (state_machine<Derived,HistoryPolicy,CopyPolicy>::*pf) (Event const& evt) =
- &state_machine<Derived,HistoryPolicy,CopyPolicy>::process_event;
+ execute_return (state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>::*pf) (Event const& evt) =
+ &state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>::process_event;
             transition_fct f = boost::bind(pf,this,evt);
             m_events_queue.push(f);
             return boost::make_tuple(HANDLED_TRUE,&this->m_states);
@@ -664,8 +663,8 @@
                 boost::bind(boost::apply<bool>(),
                     boost::bind(deref<flag_handler>(),
                         boost::bind(plus2<flag_handler*,int>(),
- flags_entries, ::_2)),
- boost::ref(*this)), ::_1));
+ flags_entries, _2)),
+ boost::ref(*this)), _1));
     }
     // checks if a flag is active using no binary op if 1 region, or OR if > 1 regions
     template <class Flag>
@@ -674,10 +673,19 @@
         typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
         return FlagHelper<Flag,(nr_regions::value>1)>::helper(*this,get_entries_for_flag<Flag>());
     }
-
+ // visit the currently active states (if these are defined as visitable
+ // by implementing accept)
+ void visit_current_states(VisitorBase& vis)
+ {
+ typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
+ for (int i=0; i<nr_regions::value;++i)
+ {
+ VisitablePolicy::execute(m_states[i],vis);
+ }
+ }
  protected: // interface for the derived class
      typedef std::vector<pstate_base> pstate_base_list;
-
+
      // helper used to fill the initial states
      struct init_states
      {
@@ -694,13 +702,16 @@
      };
      // Construct with the default initial states
      state_machine()
- : m_states(),
- m_events_queue() ,
- m_deferred_events_queue(),
- m_history(),
- m_state_list(),
- m_event_processing(false),
- m_is_included(false)
+ :state_base()
+ ,VisitablePolicy()
+ ,CopyPolicy()
+ ,m_states()
+ ,m_events_queue()
+ ,m_deferred_events_queue()
+ ,m_history()
+ ,m_state_list()
+ ,m_event_processing(false)
+ ,m_is_included(false)
      {
          typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
          m_states.reserve(nr_regions::value);
@@ -711,18 +722,22 @@
              initial_states, boost::msm::wrap<mpl::placeholders::_1>
>(init_states(m_states));
          m_history.set_initial_states(m_states);
+ // create states
          fill_states(this);
      }
      // template constructor. Needed only for sub-fsms having exit pseudo states.
      template <class ContainingSM>
      state_machine(ContainingSM* containing_sm)
- : m_states(),
- m_events_queue() ,
- m_deferred_events_queue(),
- m_history(),
- m_state_list(),
- m_event_processing(false),
- m_is_included(true)
+ :state_base()
+ ,VisitablePolicy()
+ ,CopyPolicy()
+ ,m_states()
+ ,m_events_queue()
+ ,m_deferred_events_queue()
+ ,m_history()
+ ,m_state_list()
+ ,m_event_processing(false)
+ ,m_is_included(true)
      {
          typedef typename get_number_of_regions<typename Derived::initial_state>::type nr_regions;
          m_states.reserve(nr_regions::value);
@@ -733,10 +748,12 @@
              initial_states, boost::msm::wrap<mpl::placeholders::_1>
>(init_states(m_states));
          m_history.set_initial_states(m_states);
+ // create states
          fill_states(containing_sm);
      }
      // assignment operator using the copy policy to decide if non_copyable, shallow or deep copying is necessary
- state_machine<Derived,HistoryPolicy,CopyPolicy>& operator= (state_machine<Derived,HistoryPolicy,CopyPolicy> const& rhs)
+ state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>& operator=
+ (state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy> const& rhs)
      {
          if (this != &rhs)
          {
@@ -745,7 +762,8 @@
          }
         return *this;
      }
- state_machine<Derived,HistoryPolicy,CopyPolicy> (state_machine<Derived,HistoryPolicy,CopyPolicy> const& rhs):CopyPolicy(rhs)
+ state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>
+ (state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy> const& rhs):CopyPolicy(rhs)
      {
         if (this != &rhs)
         {
@@ -1039,7 +1057,7 @@
     template <class Flag,bool orthogonalStates>
     struct FlagHelper
     {
- static bool helper(state_machine<Derived,HistoryPolicy,CopyPolicy>& sm,flag_handler* )
+ static bool helper(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>& sm,flag_handler* )
         {
             // by default we use OR to accumulate the flags
             return sm.is_flag_active<Flag,Flag_OR>();
@@ -1048,7 +1066,7 @@
     template <class Flag>
     struct FlagHelper<Flag,false>
     {
- static bool helper(state_machine<Derived,HistoryPolicy,CopyPolicy>& sm,flag_handler* flags_entries)
+ static bool helper(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>& sm,flag_handler* flags_entries)
         {
             // just one active state, so we can call operator[] with 0
             return flags_entries[sm.current_state()[0]](sm);
@@ -1059,15 +1077,15 @@
     template <class StateType,class Flag>
     struct FlagHandler
     {
- static bool flag_true(state_machine<Derived,HistoryPolicy,CopyPolicy>& )
+ static bool flag_true(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>& )
         {
             return true;
         }
- static bool flag_false(state_machine<Derived,HistoryPolicy,CopyPolicy>& )
+ static bool flag_false(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>& )
         {
             return false;
         }
- static bool forward(state_machine<Derived,HistoryPolicy,CopyPolicy>& fsm)
+ static bool forward(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>& fsm)
         {
             typedef typename create_stt<Derived>::type stt;
             return (static_cast<StateType& >
@@ -1141,7 +1159,7 @@
     template <class State, class Enable=void>
     struct create_state_helper
     {
- static void set_sm(state_machine<Derived,HistoryPolicy,CopyPolicy>* ,pstate_base )
+ static void set_sm(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* ,pstate_base )
         {
                 // state doesn't need its sm
         }
@@ -1150,7 +1168,7 @@
     template <class State>
     struct create_state_helper<State,typename boost::enable_if<typename State::needs_sm >::type>
     {
- static void set_sm(state_machine<Derived,HistoryPolicy,CopyPolicy>* sm,pstate_base new_state)
+ static void set_sm(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* sm,pstate_base new_state)
         {
                 // create and set the fsm
                 static_cast<State*>(new_state.get())->set_sm_ptr(static_cast<Derived*>(sm));
@@ -1161,7 +1179,7 @@
     template<class ContainingSM>
     struct add_state
     {
- add_state(state_machine<Derived,HistoryPolicy,CopyPolicy>* self_,ContainingSM* sm)
+ add_state(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* self_,ContainingSM* sm)
                 : self(self_),containing_sm(sm){}
 
         // State is a sub fsm with exit pseudo states and gets a pointer to this fsm, so it can build a callback
@@ -1192,7 +1210,7 @@
             execute_return (ContainingSM::*pf) (typename StateType::event const& evt)=
                 &ContainingSM::process_event;
             boost::function<execute_return (typename StateType::event const&)> fct =
- boost::bind(pf,containing_sm,::_1);
+ boost::bind(pf,containing_sm,_1);
             static_cast<StateType*>(to_return)->set_forward_fct(fct);
             return to_return;
         }
@@ -1207,16 +1225,20 @@
             pstate_base new_state (this->new_state_helper<State>());
             self->m_state_list[state_id]= new_state;
             create_state_helper<State>::set_sm(self,new_state);
+ // create a visitor callback
+ self->insert(state_id,boost::bind(&State::accept,
+ static_cast<State*>(new_state.get()),_1) );
         }
     private:
- state_machine<Derived,HistoryPolicy,CopyPolicy>* self;
+ state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* self;
         ContainingSM* containing_sm;
     };
 
      // helper used to copy every state if needed
      struct copy_helper
      {
- copy_helper(pstate_base_list& to_fill,const pstate_base_list& rhs,state_machine<Derived,HistoryPolicy,CopyPolicy>* sm):
+ copy_helper(pstate_base_list& to_fill,const pstate_base_list& rhs,
+ state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* sm):
             m_tofill_states(to_fill),m_rhs(rhs),m_sm(sm){}
          template <class StateType>
          void operator()(boost::msm::wrap<StateType> const& )
@@ -1233,14 +1255,15 @@
          }
          pstate_base_list& m_tofill_states;
          const pstate_base_list& m_rhs;
- state_machine<Derived,
- HistoryPolicy,CopyPolicy>* m_sm;
+ state_machine<Derived,HistoryPolicy,
+ VisitablePolicy,CopyPolicy>* m_sm;
      };
 
      // copy functions for shallow or deep copy (no need of a 3rd version for NoCopy as noncopyable handles it)
      template <class IsShallowCopy>
      typename boost::disable_if<typename IsShallowCopy::type,void >::type
- do_copy (state_machine<Derived,HistoryPolicy,CopyPolicy> const& rhs,boost::msm::dummy<0> = 0)
+ do_copy (state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy> const& rhs,
+ boost::msm::dummy<0> = 0)
      {
          // deep copy simply assigns the data
          m_states = rhs.m_states;
@@ -1254,7 +1277,8 @@
      }
      template <class IsShallowCopy>
      typename boost::enable_if<typename IsShallowCopy::type,void >::type
- do_copy (state_machine<Derived,HistoryPolicy,CopyPolicy> const& rhs,boost::msm::dummy<1> = 0)
+ do_copy (state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy> const& rhs,
+ boost::msm::dummy<1> = 0)
      {
          // shallow copy simply assigns the data
          m_states = rhs.m_states;
@@ -1323,7 +1347,7 @@
      // helper used to set the correct state as active state upon entry into a fsm
      struct direct_event_start_helper
      {
- direct_event_start_helper(state_machine<Derived,HistoryPolicy,CopyPolicy>* self_):self(self_){}
+ direct_event_start_helper(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* self_):self(self_){}
          // this variant is for the standard case, entry due to activation of the containing FSM
          template <class EventType>
          typename boost::disable_if<typename has_direct_entry<EventType>::type,void>::type
@@ -1392,11 +1416,11 @@
          }
      private:
          // helper for the fork case, does almost like the direct entry
- state_machine<Derived,HistoryPolicy,CopyPolicy>* self;
+ state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* self;
          template <class EventType>
          struct fork_helper
          {
- fork_helper(state_machine<Derived,HistoryPolicy,CopyPolicy>* self_,EventType const& evt_):
+ fork_helper(state_machine<Derived,HistoryPolicy,VisitablePolicy,CopyPolicy>* self_,EventType const& evt_):
                 helper_self(self_),helper_evt(evt_){}
              template <class StateType>
              void operator()(boost::msm::wrap<StateType> const& )
@@ -1409,7 +1433,8 @@
                  helper_self->m_states[StateType::zone_index] = state_id;
              }
          private:
- state_machine<Derived,HistoryPolicy,CopyPolicy>* helper_self;
+ state_machine<Derived,HistoryPolicy,
+ VisitablePolicy,CopyPolicy>* helper_self;
              EventType const& helper_evt;
          };
      };
@@ -1574,6 +1599,7 @@
         BOOST_STATIC_CONSTANT(int, max_state = (mpl::size<state_list>::value));
         // allocate the place without reallocation
         m_state_list.resize(max_state);
+ VisitablePolicy::fill_visitors(max_state);
         mpl::for_each<
                 state_list,boost::msm::wrap<mpl::placeholders::_1>
>(add_state<ContainingSM>(this,containing_sm));
@@ -1601,6 +1627,11 @@
         }
     };
 public:
+ template <class Composite,class Event>
+ struct make_frow
+ {
+ typedef frow<Composite,Event> type;
+ };
     // gets the transition table from a composite and make from it a forwarding row
     template <class Composite>
     struct get_transition_table_as_frow
@@ -1612,6 +1643,7 @@
         typedef typename mpl::fold<
             all_events, mpl::vector<>,
             mpl::push_back<mpl::placeholders::_1,
+ /*typename mpl::apply<make_frow<mpl::placeholders::_,mpl::placeholders::_>,Composite,mpl::placeholders::_2 >::type*/
                            frow<Composite,mpl::placeholders::_2> > >::type type;
     };
 
@@ -1631,7 +1663,7 @@
>::type type;
     };
 private:
- template <class Fsm, class History, class Copy,class Stt, class Event>
+ template <class Fsm, class History,class Visitable, class Copy,class Stt, class Event>
     friend struct dispatch_table;
     template <typename T1,class Event> friend struct frow;
 

Added: sandbox/msm/boost/msm/visitable_policies.hpp
==============================================================================
--- (empty file)
+++ sandbox/msm/boost/msm/visitable_policies.hpp 2009-01-29 18:03:36 EST (Thu, 29 Jan 2009)
@@ -0,0 +1,71 @@
+#ifndef VISITABLE_POLICIES_H
+#define VISITABLE_POLICIES_H
+// 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)
+//
+
+#include <vector>
+#include <boost/function.hpp>
+
+
+namespace boost { namespace msm
+{
+// base class for states wanting to be visited
+struct VisitorBase
+{
+ virtual ~VisitorBase(){}
+};
+
+ // dummy policy when visitable states are not desired
+ class NotVisitableStates
+ {
+ public:
+ NotVisitableStates(){}
+ protected:
+ void fill_visitors(int number_of_states)
+ {
+ }
+ template <class FCT>
+ void insert(int index,FCT fct)
+ {
+ }
+ void execute(int index,VisitorBase& vis)
+ {
+ }
+ };
+
+ // policy adding support of visitable states
+ class VisitableStates
+ {
+ public:
+ VisitableStates():m_state_visitors(){}
+ protected:
+ void fill_visitors(int number_of_states)
+ {
+ m_state_visitors.resize(number_of_states);
+ }
+ template <class FCT>
+ void insert(int index,FCT fct)
+ {
+ m_state_visitors[index]=fct;
+ }
+ void execute(int index,VisitorBase& vis)
+ {
+ m_state_visitors[index](vis);
+ }
+ private:
+ typedef boost::function<void (VisitorBase&)> visitor_fct;
+ typedef std::vector<visitor_fct> visitors;
+ visitors m_state_visitors;
+ };
+} } //boost::msm
+
+
+#endif //VISITABLE_POLICIES_H

Modified: sandbox/msm/libs/msm/doc/SM.cpp
==============================================================================
--- sandbox/msm/libs/msm/doc/SM.cpp (original)
+++ sandbox/msm/libs/msm/doc/SM.cpp 2009-01-29 18:03:36 EST (Thu, 29 Jan 2009)
@@ -41,8 +41,17 @@
       player& m_player;
   };
 
+ // an easy visitor
+ struct SomeVisitor: public VisitorBase
+ {
+ void visit_state(state_base* astate)
+ {
+ std::cout << "visiting state:" << typeid(*astate).name() << std::endl;
+ }
+ };
+
   // Concrete FSM implementation
- struct player : public state_machine<player>
+ struct player : public state_machine<player,NoHistory,VisitableStates>
   {
       // The list of FSM states
       struct Empty : public state<>
@@ -53,6 +62,10 @@
                         void on_entry(Event const& ) {std::cout << "entering: Empty" << std::endl;}
                         template <class Event>
                         void on_exit(Event const& ) {std::cout << "leaving: Empty" << std::endl;}
+ void accept(VisitorBase& vis)
+ {
+ static_cast<SomeVisitor*>(&vis)->visit_state(this);
+ }
       };
       struct Open : public state<>
       {
@@ -62,6 +75,10 @@
                         void on_entry(Event const& ) {std::cout << "entering: Open" << std::endl;}
                         template <class Event>
                         void on_exit(Event const& ) {std::cout << "leaving: Open" << std::endl;}
+ void accept(VisitorBase& vis)
+ {
+ static_cast<SomeVisitor*>(&vis)->visit_state(this);
+ }
       };
       // a state needing a pointer to the containing state machine
       // and using for this the non-default policy
@@ -82,7 +99,7 @@
       // then it will remember the last active state and reactivate it
       // also possible: AlwaysHistory, the last active state will always be reactivated
       // or NoHistory, always restart from the initial state
- struct Playing : public state_machine<Playing,ShallowHistory<mpl::vector<end_pause> > >
+ struct Playing : public state_machine<Playing,ShallowHistory<mpl::vector<end_pause> >,VisitableStates >
       {
                         // when playing, the CD is loaded and we are in either pause or playing (duh)
                         typedef mpl::vector2<PlayingPaused,CDLoaded> flag_list;
@@ -90,7 +107,12 @@
                         void on_entry(Event const& ) {std::cout << "entering: Playing" << std::endl;}
                         template <class Event>
                         void on_exit(Event const& ) {std::cout << "leaving: Playing" << std::endl;}
-
+ void accept(VisitorBase& vis)
+ {
+ static_cast<SomeVisitor*>(&vis)->visit_state(this);
+ // visit substates
+ visit_current_states(vis);
+ }
           // The list of FSM states
           // the Playing state machine contains a state which is himself a state machine
           // so we have a SM containing a SM containing a SM
@@ -101,7 +123,10 @@
                           void on_entry(Event const& ) {std::cout << "starting: First song" << std::endl;}
                           template <class Event>
                           void on_exit(Event const& ) {std::cout << "finishing: First Song" << std::endl;}
-
+ void accept(VisitorBase& vis)
+ {
+ static_cast<SomeVisitor*>(&vis)->visit_state(this);
+ }
                   struct LightOn : public state<>
                   {
                                  template <class Event>
@@ -345,7 +370,6 @@
                 std::cout << " -> " << state_names[p.current_state()[i]] << std::endl;
       }
   }
-
   void test()
   {
       player p;
@@ -369,7 +393,12 @@
 
       // go to Open, call on_exit on Empty, then action, then on_entry on Open
       p.process_event(open_close()); pstate(p);
+ // visiting Paused and AllOk, but only Paused cares
+ SomeVisitor vis;
+ p.visit_current_states(vis);
       p.process_event(open_close()); pstate(p);
+ // visiting Empty and AllOk, but only Empty cares
+ p.visit_current_states(vis);
 
 
       p.process_event(cd_detected("louie, louie",p));
@@ -377,6 +406,9 @@
       //p.process_event(play());
       // at this point, Play is active, along FirstSong and LightOn
       pstate(p);
+ // visiting Playing+Song1 and AllOk, but only Playing+Song1 care
+ p.visit_current_states(vis);
+
       std::cout << "PlayingPaused active:" << std::boolalpha << p.is_flag_active<PlayingPaused>() << std::endl;//=> true
       // call on_exit on LightOn,FirstSong,Play like stated in the UML spec.
       // and of course on_entry on Paused and StartBlinking
@@ -392,6 +424,9 @@
       p.process_event(NextSong());pstate(p);
       // We are now in second song, Flag inactive
       std::cout << "FirstSong active:" << std::boolalpha << p.is_flag_active<FirstSongPlaying>() << std::endl;//=> false
+ // visiting Playing+Song2 and AllOk, but only Playing cares
+ p.visit_current_states(vis);
+
       p.process_event(NextSong());pstate(p);
       // 2nd song active
       p.process_event(PreviousSong());pstate(p);

Modified: sandbox/msm/libs/msm/doc/index.html
==============================================================================
--- sandbox/msm/libs/msm/doc/index.html (original)
+++ sandbox/msm/libs/msm/doc/index.html 2009-01-29 18:03:36 EST (Thu, 29 Jan 2009)
@@ -6,11 +6,12 @@
         <META NAME="GENERATOR" CONTENT="OpenOffice.org 3.0 (Win32)">
         <META NAME="CREATED" CONTENT="20080922;21044300">
         <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
- <META NAME="CHANGED" CONTENT="20090122;21533200">
+ <META NAME="CHANGED" CONTENT="20090130;5200">
         <META NAME="Info 1" CONTENT="">
         <META NAME="Info 2" CONTENT="">
         <META NAME="Info 3" CONTENT="">
         <META NAME="Info 4" CONTENT="">
+ <META NAME="CHANGEDBY" CONTENT="Christophe Henry">
         <META NAME="CHANGEDBY" CONTENT="xtoff">
         <META NAME="CHANGEDBY" CONTENT="xtoff">
         <META NAME="CHANGEDBY" CONTENT="xtoff">
@@ -1920,7 +1921,8 @@
 <P>gcc 3.3:</P>
 <UL>
         <LI><P>the simple test completes 3 times faster with Msm</P>
- <LI><P>the composite does unfortunately not compile with Msm</P>
+ <LI><P>the composite compile but does not work (events of composites
+ lead to no_transition)</P>
 </UL>
 <H1 CLASS="western" STYLE="margin-left: 0.66cm; text-indent: -0.83cm"><A NAME="8.Compilers|outline"></A>
 Compilers</H1>
@@ -1929,7 +1931,7 @@
         <LI><P>VC8,VC9, VC9SP1</P>
         <LI><P>g++ 4.1 and g++ 4.2.3</P>
         <LI><P>partially g++ 3.3 (only <A HREF="SC%20Simple.cpp">simple
- state machines</A> in Msm version 1.0)</P>
+ state machines</A>)</P>
 </UL>
 <H1 CLASS="western" STYLE="margin-left: 0.68cm; text-indent: -0.76cm"><A NAME="8.Limitations|outline"></A>
 Limitations</H1>


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