1 //////////////////////////////////////////////////////////////////////////////
2 // Copyright 2002-2006 Andreas Huber Doenni
3 // Distributed under the Boost Software License, Version 1.0. (See accompany-
4 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //////////////////////////////////////////////////////////////////////////////
6
7
8
9 //////////////////////////////////////////////////////////////////////////////
10 // The following example program demonstrates the use of orthogonal states and
11 // state_downcast to query the state of orthogonal regions.
12 // Moreover, the use of the state type information interface is also shown.
13 //////////////////////////////////////////////////////////////////////////////
14 // #define BOOST_STATECHART_USE_NATIVE_RTTI
15
16
17 #include <boost/statechart/event.hpp>
18 #include <boost/statechart/state_machine.hpp>
19 #include <boost/statechart/simple_state.hpp>
20 #include <boost/statechart/transition.hpp>
21 #include <boost/statechart/custom_reaction.hpp>
22
23 #include <boost/mpl/list.hpp>
24 #include <boost/config.hpp>
25
26 #include <iostream>
27 #include <iomanip>
28
29 #ifdef BOOST_INTEL
30 # pragma warning( disable: 304 ) // access control not specified
31 # pragma warning( disable: 981 ) // operands are evaluated in unspecified order
32 #endif
33
34
35
36 namespace sc = boost::statechart;
37 namespace mpl = boost::mpl;
38
39
40
41 //////////////////////////////////////////////////////////////////////////////
42 struct EvNumLockPressed : sc::event< EvNumLockPressed > {};
43 struct EvCapsLockPressed : sc::event< EvCapsLockPressed > {};
44 struct EvScrollLockPressed : sc::event< EvScrollLockPressed > {};
45 struct EvRequestShutdown : sc::event< EvRequestShutdown > {};
46
47 struct Active;
48 struct Keyboard : sc::state_machine< Keyboard, Active > {};
49
50 struct NumLockOff;
51 struct CapsLockOff;
52 struct ScrollLockOff;
53 struct Active: sc::simple_state<
54 Active, Keyboard, mpl::list< NumLockOff, CapsLockOff, ScrollLockOff > >
55 {
56 typedef sc::custom_reaction< EvRequestShutdown > reactions;
57
58 sc::result react( const EvRequestShutdown & );
59 };
60
61 struct NumLockOn : sc::simple_state< NumLockOn, Active::orthogonal< 0 > >
62 {
63 typedef sc::transition< EvNumLockPressed, NumLockOff > reactions;
64 };
65
66 struct NumLockOff : sc::simple_state< NumLockOff, Active::orthogonal< 0 > >
67 {
68 typedef sc::transition< EvNumLockPressed, NumLockOn > reactions;
69 };
70
71 struct CapsLockOn : sc::simple_state< CapsLockOn, Active::orthogonal< 1 > >
72 {
73 typedef sc::transition< EvCapsLockPressed, CapsLockOff > reactions;
74 };
75
76 struct CapsLockOff : sc::simple_state< CapsLockOff, Active::orthogonal< 1 > >
77 {
78 typedef sc::transition< EvCapsLockPressed, CapsLockOn > reactions;
79 };
80
81 struct ScrollLockOn : sc::simple_state< ScrollLockOn, Active::orthogonal< 2 > >
82 {
83 typedef sc::transition< EvScrollLockPressed, ScrollLockOff > reactions;
84 };
85
86 struct ScrollLockOff : sc::simple_state< ScrollLockOff, Active::orthogonal< 2 > >
87 {
88 typedef sc::transition< EvScrollLockPressed, ScrollLockOn > reactions;
89 };
90
react(const EvRequestShutdown &)91 sc::result Active::react( const EvRequestShutdown & )
92 {
93 if ( ( state_downcast< const NumLockOff * >() != 0 ) &&
94 ( state_downcast< const CapsLockOff * >() != 0 ) &&
95 ( state_downcast< const ScrollLockOff * >() != 0 ) )
96 {
97 std::cout << "Shutdown request accepted\n";
98 return terminate();
99 }
100 else
101 {
102 std::cout << "Ignoring shutdown request\n\n";
103 return discard_event();
104 }
105 }
106
107
108 //////////////////////////////////////////////////////////////////////////////
DisplayStateConfiguration(const Keyboard & keyboard)109 void DisplayStateConfiguration( const Keyboard & keyboard )
110 {
111 char orthogonalRegion = 'a';
112
113 for ( Keyboard::state_iterator pLeafState = keyboard.state_begin();
114 pLeafState != keyboard.state_end(); ++pLeafState )
115 {
116 std::cout << "Orthogonal region " << orthogonalRegion << ": ";
117
118 const Keyboard::state_base_type * pState = &*pLeafState;
119
120 while ( pState != 0 )
121 {
122 if ( pState != &*pLeafState )
123 {
124 std::cout << " -> ";
125 }
126
127 #ifdef BOOST_STATECHART_USE_NATIVE_RTTI
128 std::cout << std::setw( 15 ) << typeid( *pState ).name();
129 #else
130 std::cout << std::setw( 15 ) <<
131 pState->custom_dynamic_type_ptr< char >();
132 #endif
133 pState = pState->outer_state_ptr();
134 }
135
136 std::cout << "\n";
137 ++orthogonalRegion;
138 }
139
140 std::cout << "\n";
141 }
142
143
144 //////////////////////////////////////////////////////////////////////////////
main()145 int main()
146 {
147 #ifndef BOOST_STATECHART_USE_NATIVE_RTTI
148 Active::custom_static_type_ptr( "Active" );
149 NumLockOn::custom_static_type_ptr( "NumLockOn" );
150 NumLockOff::custom_static_type_ptr( "NumLockOff" );
151 CapsLockOn::custom_static_type_ptr( "CapsLockOn" );
152 CapsLockOff::custom_static_type_ptr( "CapsLockOff" );
153 ScrollLockOn::custom_static_type_ptr( "ScrollLockOn" );
154 ScrollLockOff::custom_static_type_ptr( "ScrollLockOff" );
155 #endif
156
157 std::cout << "Boost.Statechart Keyboard example\n\n";
158 Keyboard keyboard;
159 keyboard.initiate();
160 DisplayStateConfiguration( keyboard );
161 keyboard.process_event( EvNumLockPressed() );
162 DisplayStateConfiguration( keyboard );
163 keyboard.process_event( EvRequestShutdown() );
164 keyboard.process_event( EvCapsLockPressed() );
165 DisplayStateConfiguration( keyboard );
166 keyboard.process_event( EvRequestShutdown() );
167 keyboard.process_event( EvScrollLockPressed() );
168 DisplayStateConfiguration( keyboard );
169 keyboard.process_event( EvRequestShutdown() );
170
171 keyboard.process_event( EvNumLockPressed() );
172 DisplayStateConfiguration( keyboard );
173 keyboard.process_event( EvRequestShutdown() );
174 keyboard.process_event( EvCapsLockPressed() );
175 DisplayStateConfiguration( keyboard );
176 keyboard.process_event( EvRequestShutdown() );
177 keyboard.process_event( EvScrollLockPressed() );
178 DisplayStateConfiguration( keyboard );
179 keyboard.process_event( EvRequestShutdown() );
180
181 return 0;
182 }
183