$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r71849 - branches/msm/msm_phoenix/libs/example
From: christophe.j.henry_at_[hidden]
Date: 2011-05-09 16:49:22
Author: chenry
Date: 2011-05-09 16:49:20 EDT (Mon, 09 May 2011)
New Revision: 71849
URL: http://svn.boost.org/trac/boost/changeset/71849
Log:
better example
Added:
   branches/msm/msm_phoenix/libs/example/logging_functors.h   (contents, props changed)
Text files modified: 
   branches/msm/msm_phoenix/libs/example/SimplePhoenix.cpp |   177 ++++++++++++++++++++++++++++++++------- 
   1 files changed, 142 insertions(+), 35 deletions(-)
Modified: branches/msm/msm_phoenix/libs/example/SimplePhoenix.cpp
==============================================================================
--- branches/msm/msm_phoenix/libs/example/SimplePhoenix.cpp	(original)
+++ branches/msm/msm_phoenix/libs/example/SimplePhoenix.cpp	2011-05-09 16:49:20 EDT (Mon, 09 May 2011)
@@ -11,11 +11,10 @@
 #include <vector>
 #include <iostream>
 
-#include <boost/phoenix/core.hpp>
-#include <boost/phoenix/function.hpp>
-#include <boost/phoenix/core/argument.hpp>
-
+#include <boost/phoenix/phoenix.hpp>
 
+// add phoenix support in eUML
+#define BOOST_MSM_EUML_PHOENIX_SUPPORT
 #include <boost/msm/back/state_machine.hpp>
 #include <boost/msm/front/euml/euml.hpp>
 
@@ -25,31 +24,51 @@
 namespace msm = boost::msm;
 using namespace boost::phoenix;
 
-using boost::phoenix::arg_names::arg1;
-using boost::phoenix::arg_names::arg2;
-using boost::phoenix::arg_names::arg3;
-using boost::phoenix::arg_names::arg4;
-//namespace boost { namespace phoenix { namespace arg_names
-//{
-//    expression::argument<3>::type const arg4 = {};
-//
-//}} }
-using boost::phoenix::arg_names::arg4;
 // entry/exit/action/guard logging functors
 #include "logging_functors.h"
 
 namespace  // Concrete FSM implementation
 {
     // events
+    BOOST_MSM_EUML_EVENT(end_pause)
+    BOOST_MSM_EUML_EVENT(stop)
+    BOOST_MSM_EUML_EVENT(pause)
     BOOST_MSM_EUML_EVENT(open_close)
+    struct play_event : boost::msm::front::euml::euml_event<play_event>
+    {
+    };
+    play_event play;
+
+    enum DiskTypeEnum
+    {
+        DISK_CD=0,
+        DISK_DVD=1
+    };
+    // A "complicated" event type that carries some data.
+    struct cd_detected_event : boost::msm::front::euml::euml_event<cd_detected_event>
+    {
+        cd_detected_event(){}
+        cd_detected_event(std::string const& name,DiskTypeEnum disk):cd_name(name),cd_type(disk){}
+        std::string cd_name;
+        DiskTypeEnum cd_type;
+    };
+    // define an instance for a nicer transition table
+    cd_detected_event cd_detected;
 
     // Concrete FSM implementation 
     // The list of FSM states
+    // state not needing any entry or exit
+    BOOST_MSM_EUML_STATE((),Paused)
+
+    // states with standard eUML actions
+    BOOST_MSM_EUML_STATE(( Stopped_Entry,Stopped_Exit ),Stopped)
+    BOOST_MSM_EUML_STATE(( Playing_Entry,Playing_Exit ),Playing)
 
+    // a "standard" msm state
     struct Empty_impl : public msm::front::state<> , public euml_state<Empty_impl>
     {
         // this allows us to add some functions
-        void activate_empty() {std::cout << "switching to Empty " << std::endl;}
+        void foo() {std::cout << "Empty::foo " << std::endl;}
         // standard entry behavior
         template <class Event,class FSM>
         void on_entry(Event const& evt,FSM& fsm) 
@@ -65,40 +84,110 @@
     //instance for use in the transition table
     Empty_impl const Empty;
 
-    // define more states
-    BOOST_MSM_EUML_STATE(( Open_Entry,Open_Exit ),Open)
+    // entry and exit actions as phoenix functions
+    struct open_entry_impl
+    {
+        typedef void result_type;
+        void operator()()
+        {
+            cout << "entering: Open" << endl;
+        }
+    };
+    boost::phoenix::function<open_entry_impl> open_entry;
+    struct open_exit_impl
+    {
+        typedef void result_type;
+        void operator()()
+        {
+            cout << "leaving: Open" << endl;
+        }
+    };
+    boost::phoenix::function<open_exit_impl> open_exit;
+
+    // a state using phoenix for entry/exit actions
+    BOOST_MSM_EUML_STATE(( open_entry(),open_exit() ),Open)
 
-    struct some_guard_impl
+    // actions and guards using boost::phoenix
+    struct start_playback_impl
+    {
+        typedef void result_type;
+        void operator()()
+        {
+            cout << "calling: start_playback" << endl;
+        }
+    };
+    boost::phoenix::function<start_playback_impl> start_playback;
+
+    // a guard taking the event as argument
+    struct good_disk_format_impl
     {
         typedef bool result_type;
 
-        bool operator()()
+        template <class Event>
+        bool operator()(Event const& evt)
         {
-            cout << "calling: some_guard" << endl;
+            // to test a guard condition, let's say we understand only CDs, not DVD
+            if (evt.cd_type!=DISK_CD)
+            {
+                std::cout << "wrong disk, sorry" << std::endl;
+                return false;
+            }
+            std::cout << "good disk" << std::endl;
             return true;
         }
     };
-    boost::phoenix::function<some_guard_impl> some_guard;
-    
-    struct some_action_impl
+    boost::phoenix::function<good_disk_format_impl> good_disk_format;
+
+    // a simple action
+    struct store_cd_info_impl
     {
         typedef void result_type;
-
         void operator()()
         {
-            cout << "calling: some_action" << endl;
+            cout << "calling: store_cd_info" << endl;
         }
     };
-    boost::phoenix::function<some_action_impl> some_action;
+    boost::phoenix::function<store_cd_info_impl> store_cd_info;
 
-    // replaces the old transition table
+    // an action taking the fsm as argument and sending it a new event
+    struct process_play_impl
+    {
+        typedef void result_type;
+
+        template <class Fsm>
+        void operator()(Fsm& fsm)
+        {
+            cout << "queuing a play event" << endl;
+            fsm.process_event(play);
+        }
+    };
+    boost::phoenix::function<process_play_impl> process_play;
+
+ 
+    // transition table. Actions and guards are written as phoenix functions
     BOOST_MSM_EUML_TRANSITION_TABLE((
-          Open     == Empty     + open_close  [some_guard()&&some_guard()] / (some_action(),some_action())
-          
-          // these ones are also ok
-          //Open     == Empty     + open_close  / some_action()
-          //Empty     + open_close  [some_guard()] / some_action()
-          //Open     == Empty   / some_action()
+          //an action without arguments
+          Playing   == Stopped  + play        / start_playback()                            , 
+          Playing   == Paused   + end_pause                                                 ,
+          //  +------------------------------------------------------------------------------+
+          Empty     == Open     + open_close                                                ,
+          //  +------------------------------------------------------------------------------+
+          Open      == Empty    + open_close                                                ,
+          Open      == Paused   + open_close                                                ,
+          Open      == Stopped  + open_close                                                ,
+          Open      == Playing  + open_close                                                ,
+          //  +------------------------------------------------------------------------------+
+          Paused    == Playing  + pause                                                     ,
+          //  +------------------------------------------------------------------------------+
+          Stopped   == Playing  + stop                                                      ,
+          Stopped   == Paused   + stop                                                      ,
+          // a guard taking the event as argument
+          // and an action made of a phoenix expression of 2 actions
+          // _event is a placeholder for the current event
+          // _fsm is a placeholder for the current state machine
+          Stopped   == Empty    + cd_detected [good_disk_format(_event)] 
+                                              / (store_cd_info(),process_play(_fsm)),
+          Stopped   == Stopped  + stop                            
           //  +------------------------------------------------------------------------------+
          ),transition_table)
 
@@ -135,10 +224,28 @@
         player p;
         // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
         p.start();
-        // note that we write open_close and not open_close(), like usual. Both are possible with eUML, but 
-        // you now have less to type.
         // go to Open, call on_exit on Empty, then action, then on_entry on Open
         p.process_event(open_close); pstate(p);
+        p.process_event(open_close); pstate(p);
+        // will be rejected, wrong disk type
+        p.process_event(
+            cd_detected_event("louie, louie",DISK_DVD)); pstate(p);
+        p.process_event(
+            cd_detected_event("louie, louie",DISK_CD)); pstate(p);
+        // no need to call play as the previous event does it in its action method
+        //p.process_event(play);
+
+        // at this point, Play is active      
+        p.process_event(pause); pstate(p);
+        // go back to Playing
+        p.process_event(end_pause);  pstate(p);
+        p.process_event(pause); pstate(p);
+        p.process_event(stop);  pstate(p);
+        // event leading to the same state
+        // no action method called as none is defined in the transition table
+        p.process_event(stop);  pstate(p);
+        // test call to no_transition
+        p.process_event(pause); pstate(p);
     }
 }
 
Added: branches/msm/msm_phoenix/libs/example/logging_functors.h
==============================================================================
--- (empty file)
+++ branches/msm/msm_phoenix/libs/example/logging_functors.h	2011-05-09 16:49:20 EDT (Mon, 09 May 2011)
@@ -0,0 +1,370 @@
+// Copyright 2010 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 LOGGING_FUNCTORS
+#define LOGGING_FUNCTORS
+
+BOOST_MSM_EUML_ACTION(Empty_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "entering: Empty" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Empty_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "leaving: Empty" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Open_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "entering: Open" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Open_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "leaving: Open" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Stopped_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "entering: Stopped" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Stopped_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "leaving: Stopped" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(AllOk_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: AllOk" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(AllOk_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: AllOk" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(ErrorMode_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: ErrorMode" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(ErrorMode_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: ErrorMode" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Playing_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "entering: Playing" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Playing_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "leaving: Playing" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Song1_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: First song" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Song1_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: First Song" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Song2_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: Second song" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Song2_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: Second Song" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Song3_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: Third song" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Song3_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: Third Song" << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(Region2State1_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: Region2State1" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Region2State1_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: Region2State1" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Region2State2_Entry)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "starting: Region2State2" << std::endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(Region2State2_Exit)
+{
+    template <class Event,class FSM,class STATE>
+    void operator()(Event const&,FSM&,STATE& )
+    {
+        std::cout << "finishing: Region2State2" << std::endl;
+    }
+};
+// transition actions for Playing
+BOOST_MSM_EUML_ACTION(start_next_song)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        std::cout << "Playing::start_next_song" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(start_prev_song)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        std::cout << "Playing::start_prev_song" << endl;
+    }
+};
+
+// transition actions
+BOOST_MSM_EUML_ACTION(start_playback)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::start_playback" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(open_drawer)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::open_drawer" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(close_drawer)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::close_drawer" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(store_cd_info)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const&, FSM& ,SourceState& ,TargetState& )
+    {
+        cout << "player::store_cd_info" << endl;
+        // it is now easy to use the message queue. 
+        // alternatively to the proces_ in the transition table, we could write:
+        // fsm.process_event(play());
+    }
+};
+BOOST_MSM_EUML_ACTION(stop_playback)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::stop_playback" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(pause_playback)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::pause_playback" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(resume_playback)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::resume_playback" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(stop_and_open)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::stop_and_open" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(stopped_again)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::stopped_again" << endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(report_error)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::report_error" << endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(report_end_error)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+    {
+        cout << "player::report_end_error" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(internal_action1)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const&, FSM& ,SourceState& ,TargetState& )
+    {
+        cout << "Open::internal action1" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(internal_action2)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const&, FSM& ,SourceState& ,TargetState& )
+    {
+        cout << "Open::internal action2" << endl;
+    }
+};
+BOOST_MSM_EUML_ACTION(internal_action)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    void operator()(EVT const&, FSM& ,SourceState& ,TargetState& )
+    {
+        cout << "Open::internal action" << endl;
+    }
+};
+enum DiskTypeEnum
+{
+    DISK_CD=0,
+    DISK_DVD=1
+};
+
+// Handler called when no_transition detected
+BOOST_MSM_EUML_ACTION(Log_No_Transition)
+{
+    template <class FSM,class Event>
+    void operator()(Event const& e,FSM&,int state)
+    {
+        std::cout << "no transition from state " << state
+            << " on event " << typeid(e).name() << std::endl;
+    }
+};
+
+BOOST_MSM_EUML_ACTION(internal_guard1)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    bool operator()(EVT const&, FSM& ,SourceState& ,TargetState& )
+    {
+        cout << "Open::internal guard1" << endl;
+        return false;
+    }
+};
+BOOST_MSM_EUML_ACTION(internal_guard2)
+{
+    template <class FSM,class EVT,class SourceState,class TargetState>
+    bool operator()(EVT const&, FSM& ,SourceState& ,TargetState& )
+    {
+        cout << "Open::internal guard2" << endl;
+        return false;
+    }
+};
+#endif // LOGGING_FUNCTORS