~ubuntu-branches/debian/sid/boost1.49/sid

« back to all changes in this revision

Viewing changes to libs/msm/doc/PDF/examples/SimpleTimer.cpp

  • Committer: Package Import Robot
  • Author(s): Steve M. Robbins
  • Date: 2012-02-26 00:31:44 UTC
  • Revision ID: package-import@ubuntu.com-20120226003144-eaytp12cbf6ubpms
Tags: upstream-1.49.0
ImportĀ upstreamĀ versionĀ 1.49.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2010 Christophe Henry
 
2
// henry UNDERSCORE christophe AT hotmail DOT com
 
3
// This is an extended version of the state machine available in the boost::mpl library
 
4
// Distributed under the same license as the original.
 
5
// Copyright for the original version:
 
6
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
 
7
// under the Boost Software License, Version 1.0. (See accompanying
 
8
// file LICENSE_1_0.txt or copy at
 
9
// http://www.boost.org/LICENSE_1_0.txt)
 
10
 
 
11
#include <vector>
 
12
#include <iostream>
 
13
 
 
14
#include <boost/msm/back/state_machine.hpp>
 
15
#include <boost/msm/front/euml/euml.hpp>
 
16
 
 
17
using namespace std;
 
18
using namespace boost::msm::front::euml;
 
19
namespace msm = boost::msm;
 
20
 
 
21
// how long the timer will ring when countdown elapsed.
 
22
#define RINGING_TIME 5
 
23
 
 
24
namespace  // Concrete FSM implementation
 
25
{
 
26
    // events
 
27
    BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_timer)
 
28
    BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_timer ), start_timer_attr)
 
29
    BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(start_timer,start_timer_attr)
 
30
 
 
31
    BOOST_MSM_EUML_EVENT(stop_timer)
 
32
 
 
33
    BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_tick)
 
34
    BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_tick ), tick_attr)
 
35
    BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(tick,tick_attr)
 
36
 
 
37
    BOOST_MSM_EUML_EVENT(start_ringing)
 
38
 
 
39
    // Concrete FSM implementation 
 
40
 
 
41
    // The list of FSM states
 
42
    BOOST_MSM_EUML_ACTION(Stopped_Entry)
 
43
    {
 
44
        template <class Event,class FSM,class STATE>
 
45
        void operator()(Event const&,FSM&,STATE& )
 
46
        {
 
47
            std::cout << "entering: Stopped" << std::endl;
 
48
        }
 
49
    };
 
50
    BOOST_MSM_EUML_STATE(( Stopped_Entry ),Stopped)
 
51
 
 
52
    BOOST_MSM_EUML_ACTION(Started_Entry)
 
53
    {
 
54
        template <class Event,class FSM,class STATE>
 
55
        void operator()(Event const&,FSM&,STATE& )
 
56
        {
 
57
            std::cout << "entering: Started" << std::endl;
 
58
        }
 
59
    };
 
60
 
 
61
    BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_counter)
 
62
    BOOST_MSM_EUML_STATE((  Started_Entry,
 
63
                            no_action,
 
64
                            attributes_ << m_counter
 
65
                  ),
 
66
                  Started)
 
67
 
 
68
    BOOST_MSM_EUML_ACTION(Ringing_Entry)
 
69
    {
 
70
        template <class Event,class FSM,class STATE>
 
71
        void operator()(Event const&,FSM&,STATE& )
 
72
        {
 
73
            std::cout << "entering: Ringing" << std::endl;
 
74
        }
 
75
    };
 
76
    BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_ringing_cpt)
 
77
    BOOST_MSM_EUML_STATE((  Ringing_Entry,
 
78
                            no_action,
 
79
                            attributes_ << m_ringing_cpt
 
80
                  ),
 
81
                  Ringing)
 
82
 
 
83
    // external function
 
84
    void do_ring(int ringing_time) {std::cout << "ringing " << ringing_time << " s" << std::endl;}
 
85
    // create functor and eUML function
 
86
    BOOST_MSM_EUML_FUNCTION(Ring_ , do_ring , ring_ , void , void )
 
87
 
 
88
    // replaces the old transition table
 
89
    BOOST_MSM_EUML_TRANSITION_TABLE((
 
90
        //  +------------------------------------------------------------------------------+
 
91
          // When we start the countdown, the countdown value is not hardcoded but contained in the start_timer event.
 
92
          // We copy this value into Started
 
93
          Started     == Stopped + start_timer /(target_(m_counter)= event_(m_timer))         ,
 
94
          Stopped     == Started + stop_timer                                                 ,
 
95
          // internal transition
 
96
          Started + tick
 
97
                    // we here use the message queue to move to Started when the countdown is finished
 
98
                    // to do this we put start_ringing into the message queue
 
99
                    / if_then_( (source_(m_counter) -= event_(m_tick) ) <= Int_<0>(),
 
100
                                 process_(start_ringing) )                                        ,
 
101
          // when we start ringing, we give to the state its hard-coded ringing time.
 
102
          Ringing     == Started + start_ringing 
 
103
                           / (target_(m_ringing_cpt) = Int_<RINGING_TIME>(),
 
104
                              // call the external do_ring function
 
105
                              ring_(Int_<RINGING_TIME>()))                                          ,
 
106
          // to change a bit, we now do not use the message queue but a transition conflict to solve the same problem.
 
107
          // When tick is fired, we have an internal transition Ringing -> Ringing, as long as Counter > 0
 
108
          Ringing + tick [ source_(m_ringing_cpt) - event_(m_tick) > Int_<0>() ] 
 
109
                             /(target_(m_ringing_cpt) -= event_(m_tick) )                           ,
 
110
          // And we move to Stopped when the counter is 0
 
111
          Stopped     == Ringing + tick[source_(m_ringing_cpt)-event_(m_tick) <= Int_<0>()]   ,
 
112
          // we let the user manually stop the ringing by pressing any button
 
113
          Stopped     == Ringing + stop_timer                                                 ,
 
114
          Stopped     == Ringing + start_timer
 
115
          //  +------------------------------------------------------------------------------+
 
116
          ),transition_table)
 
117
 
 
118
    // create a state machine "on the fly"
 
119
    BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
 
120
                                        init_ << Stopped // Init State
 
121
                                        ),
 
122
                                      SimpleTimer_) //fsm name
 
123
 
 
124
    // choice of back-end
 
125
    typedef msm::back::state_machine<SimpleTimer_> SimpleTimer;
 
126
 
 
127
    //
 
128
    // Testing utilities.
 
129
    //
 
130
    static char const* const state_names[] = { "Stopped", "Started","Ringing" };
 
131
    void pstate(SimpleTimer const& p)
 
132
    {
 
133
        std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
 
134
    }
 
135
 
 
136
    void test()
 
137
    {        
 
138
        SimpleTimer p;
 
139
        // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
 
140
        p.start();
 
141
 
 
142
        p.process_event(start_timer(5));pstate(p); //timer set to 5 ticks
 
143
        p.process_event(tick(2));pstate(p);
 
144
        p.process_event(tick(1));pstate(p);
 
145
        p.process_event(tick(1));pstate(p);
 
146
        p.process_event(tick(1));pstate(p);
 
147
        // we are now ringing, let it ring a bit
 
148
        p.process_event(tick(2));pstate(p);
 
149
        p.process_event(tick(1));pstate(p);
 
150
        p.process_event(tick(1));pstate(p);
 
151
        p.process_event(tick(1));pstate(p);
 
152
    }
 
153
}
 
154
 
 
155
int main()
 
156
{
 
157
    test();
 
158
    return 0;
 
159
}