OpenRTM-aist 2.0.2
Loading...
Searching...
No Matches
Macho.h
Go to the documentation of this file.
1#ifndef MACHO_HPP
2#define MACHO_HPP
3
4// Macho - C++ Machine Objects
5//
6// The Machine Objects class library (in short Macho) allows the creation of
7// state machines based on the "State" design pattern in straight C++. It
8// extends the pattern with the option to create hierarchical state machines,
9// making it possible to convert the popular UML statechart notation to working
10// code in a straightforward way. Other features are entry and exit actions,
11// state histories and state variables.
12//
13// Copyright (c) 2005 by Eduard Hiti (feedback to macho@ehiti.de)
14//
15// Permission is hereby granted, free of charge, to any person obtaining a copy
16// of this software and associated documentation files (the "Software"), to deal
17// in the Software without restriction, including without limitation the rights
18// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19// copies of the Software, and to permit persons to whom the Software is
20// furnished to do so, subject to the following conditions:
21//
22// The above copyright notice and this permission notice shall be included in
23// all copies or substantial portions of the Software.
24//
25// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31// SOFTWARE.
32//
33// You are encouraged to provide any changes, extensions and corrections for
34// this software to the author at the above-mentioned email address for
35// inclusion into future versions.
36//
37//
38// Description:
39//
40// States are represented as C++ classes. The hierarchy of states follows the
41// inheritance relation between these state classes. A set of state classes for
42// a single state machine derives directly or indirectly from a top state class,
43// making it the composite state holding all other states. Events are processed
44// by calling virtual methods of the top state class. Substates redefine the
45// behaviour of these event handler methods.
46//
47// Special methods "entry", "exit" and "init" are called on state entry, state
48// exit and state initialization of super- and substates (in the order defined
49// by statechart semantics and current machine state).
50//
51// An object of type "Machine" maintains the current state of a state machine
52// and dispatches events to it. The "Machine" type is a template class
53// parametrized with the top state class of the state machine to be run.
54//
55// State data is not kept in state classes (because state class instances are
56// created just once and then reused, whereas state data should be instantiated
57// or destroyed each time its state is entered or left). State data is put in
58// "Box" types specific to each state class instead, which are managed by the
59// Machine object. Boxes are retrieved by calling the "box" method.
60// Superstate boxes are accessible by qualifiying the "box" method with the
61// state class name (e.g. TOP::box()).
62//
63// A history of entered substates can be kept for superstates. With a special
64// transition into the superstate the history substate can be reentered. History
65// can be shallow (only direct substates) or deep (any substate).
66//
67//
68// Example:
69//
70// #include "Macho.hpp"
71// #include <iostream>
72// using namespace std;
73//
74// namespace Example {
75// TOPSTATE(Top) {
76// struct Box {
77// Box() : data(0) {}
78// long data;
79// };
80//
81// STATE(Top)
82//
83// virtual void event1() {}
84// virtual void event2() {}
85//
86// private:
87// void entry();
88// void exit();
89// void init();
90// };
91//
92// SUBSTATE(Super, Top) {
93// STATE(Super)
94// HISTORY()
95//
96// private:
97// void entry();
98// void exit();
99// };
100//
101// SUBSTATE(StateA, Super) {
102// struct Box {
103// Box() : data(0) {}
104// int data;
105// };
106//
107// STATE(StateA)
108//
109// void event1();
110//
111// private:
112// void entry();
113// void exit();
114// void init(int i);
115// };
116//
117// SUBSTATE(StateB, Super) {
118// STATE(StateB)
119//
120// void event2();
121//
122// private:
123// void entry();
124// void exit();
125// };
126//
127// void Top::entry() { cout << "Top::entry" << endl; }
128// void Top::exit() { cout << "Top::exit" << endl; }
129// void Top::init() { setState<StateA>(42); }
130//
131// void Super::entry() { cout << "Super::entry" << endl; }
132// void Super::exit() { cout << "Super::exit" << endl; }
133//
134// void StateA::entry() { cout << "StateA::entry" << endl; }
135// void StateA::init(int i) { box().data = i; }
136// void StateA::exit() { cout << "StateA::exit" << endl; }
137// void StateA::event1() { setState<StateB>(); }
138//
139// void StateB::entry() { cout << "StateB::entry" << endl; }
140// void StateB::exit() { cout << "StateB::exit" << endl; }
141// void StateB::event2() { setState<StateA>(); }
142// }
143//
144// int main() {
145// Macho::Machine<Example::Top> m;
146// m->event1();
147// m->event2();
148//
149// return 0;
150// }
151//
152// Output is:
153//
154// Top::entry
155// Super::entry
156// StateA::entry
157// StateA::exit
158// StateB::entry
159// StateB::exit
160// StateA::entry
161// StateA::exit
162// Super::exit
163// Top::exit
164//
165//
166// Version History:
167//
168// 0.9.6 (released 2007-09-01):
169// - Changes to state transition semantics (see file "changes_0_9_6.txt")
170// - New mechanism for state initialization
171// - Runtime reflection on state relationships now possible
172//
173// 0.9.5 (released 2007-05-01):
174// - Introduction of parametrized state transitions
175//
176// 0.9.4 (released 2006-06-01):
177// - Snapshot functionality added
178//
179// 0.9.3 (released 2006-04-20):
180// - Code reorganization (file Macho.cpp added)
181//
182// 0.9.2 (released 2006-04-10):
183// - Memory leak plugged
184// - MSVC6 version updated
185//
186// 0.9.1 (released 2006-03-30):
187// - Introduction of persistent boxes
188// - Speed and size optimizations
189// - Machine instance can be accessed in event handlers with method "machine"
190//
191// 0.9 (released 2006-01-15):
192// - Introduction of queuable event type
193//
194// 0.8.2 (released 2005-12-15):
195// - Code size reduction by minimizing use of template classes
196//
197// 0.8.1 (released 2005-12-01):
198// - Added MSVC6 variant (see directory "msvc6")
199// - Added method "clearHistoryDeep"
200//
201// 0.8 (released 2005-11-01):
202// - Initial release
203//
204
205#include <new>
206#include <cassert>
207
208class TestAccess;
209
210
212// Check type equality at compile time.
213template<class T, class U>
215};
216
217template<class T>
218struct CheckSameType<T, T> {
219 using Check = bool;
220};
221
222
224// Various macros for state and history declaration
225
226// Use this macro to define your top state class.
227#define TOPSTATE(TOP) \
228 struct TOP : public ::Macho::Link< TOP, ::Macho::TopBase< TOP > >
229
230// Use this macro for all other state classes.
231#define SUBSTATE(STATE, SUPERSTATE) \
232 struct STATE : public ::Macho::Link< STATE, SUPERSTATE >
233
234// Use this macro in your class definition to give it state functionality
235// (mandatory). If you have a state box declare it BEFORE macro invocation!
236#define STATE(S) \
237public: \
238 using SELF = S; \
239 /* Constructor and destructor already defined: you can't (and shouldn't) have your own! */ \
240 /* For the user a state class "constructor" and "destructor" are its entry and exit method! */ \
241 S(::Macho::_StateInstance & instance) : ::Macho::Link<S, SUPER>(instance) { \
242 /* Compile time check: S must derive directly from Link<S, SUPER> */ \
243 using MustDeriveFromLink = ::CheckSameType< ::Macho::Link<S, SUPER>, LINK>::Check; \
244 } \
245 ~S() {} \
246 static const char * _state_name() { return #S; } \
247 /* Get to your Box with this method: */ \
248 Box & box() { return *static_cast<Box *>(_box()); } \
249 friend class ::_VS8_Bug_101615;
250
251// Use this macro to select deep history strategy.
252#define DEEPHISTORY() \
253private: \
254 /* If no superstate has history, SUPER::_setHistorySuper is a NOOP */ \
255 void _saveHistory(::Macho::_StateInstance & self, ::Macho::_StateInstance & /* shallow */, ::Macho::_StateInstance & deep) override\
256 { self.setHistory(&deep); SELF::SUPER::_setHistorySuper(self, deep); } \
257protected: \
258 /* Substates may use _setHistorySuper to bubble up history */ \
259 void _setHistorySuper(::Macho::_StateInstance & self, ::Macho::_StateInstance & deep) override\
260 { self.setHistorySuper(deep); } \
261public:\
262 static_assert(true, "dummy for extra semicolon warning")
263
264// Use this macro to select shallow history strategy.
265#define HISTORY() \
266private: \
267 /* If no superstate has history, SUPER::_setHistorySuper is a NOOP */ \
268 virtual void _saveHistory(::Macho::_StateInstance & self, ::Macho::_StateInstance & shallow, ::Macho::_StateInstance & deep) \
269 { self.setHistory(&shallow); SELF::SUPER::_setHistorySuper(self, deep); } \
270protected: \
271 /* Substates may use _setHistorySuper to bubble up history */ \
272 virtual void _setHistorySuper(::Macho::_StateInstance & self, ::Macho::_StateInstance & deep) \
273 { self.setHistorySuper(deep); } \
274public:\
275 static_assert(true, "dummy for extra semicolon warning")
276
277// Use this macro to have boxes survive state transitions
278#define PERSISTENT() \
279private: \
280 virtual void _deleteBox(::Macho::_StateInstance & instance) {} \
281public:
282
283
285// Everything else is put into namespace 'Macho'.
286// Some identifiers are prefixed with an underscore to prevent name clashes with
287// deriving classes or to mark things as library internal. Don't touch things
288// with an underscore prefix!
289namespace Macho {
290
291 class _MachineBase;
292
293 template<class T>
294 class Machine;
295
296 template<class T>
297 class IEvent;
298
299 class _StateInstance;
300
301 // Unique identifier of states.
302 using Key = void*;
303
304 // Also an unique identifier of states, build from consecutive integers.
305 // Use Key to get to ID.
306 using ID = unsigned int;
307
308
310 // Box for states which don't declare own Box class.
311 class _EmptyBox {
312 public:
314 };
315
316
318 // Helper functions for box creation
319 template<class B>
320 void * _createBox(void * & place) {
321 if (!place)
322 place = ::operator new(sizeof(B));
323
324 new (place) B;
325
326 void * box = place;
327 place = nullptr;
328
329 return box;
330 }
331
332 template<class B>
333 void _deleteBox(void * & box, void * & place) {
334 assert(box);
335 assert(!place);
336
337 static_cast<B *>(box)->~B();
338 place = box;
339 box = nullptr;
340 }
341
342#ifdef MACHO_SNAPSHOTS
343 template<class B>
344 void * _cloneBox(void * other) {
345 assert(other);
346 return new B(*static_cast<B *>(other));
347 }
348#endif
349
350 // Specializations for EmptyBox:
351 // EmptyBox object gets reused over and over and never is deleted.
352 template<>
353 void * _createBox<_EmptyBox>(void * & place);
354
355 template<>
356 void _deleteBox<_EmptyBox>(void * & box, void * & place);
357
358#ifdef MACHO_SNAPSHOTS
359 template<>
360 void * _cloneBox<_EmptyBox>(void * other);
361#endif
362
363
365 // Essential information pointed at by state key.
366 struct _KeyData {
368 using Predicate = bool (*)(Key);
369 using NameFn = const char* (*)();
370
371 // Get StateInstance object from key.
373
374 // Is state of given key a child state?
376
378 const ID id;
379 };
380
381
383 // Base class for all state classes.
384 // Also serves as 'Root' state. By entering this state we trigger entry
385 // and exit actions of user's top state.
387 public:
388 virtual ~_StateSpecification() = default;
389
390 static bool isChild(Key /*key*/) {
391 return false;
392 }
393
394 protected:
396 : _myStateInstance(instance)
397 {}
398
399 // Initiate transition to a new state.
400 // Template parameter S is the new state to enter.
401 // Transition is performed AFTER control flow returns to the Machine object.
402 // Initiating more than one transition is considered an error!
403 // The new state may receive parameters for its 'init' methods:
404 // setState<StateA>("someData");
405 template<class S>
406 void setState();
407
408 template<class S, class P1>
409 void setState(const P1 & p1);
410
411 template<class S, class P1, class P2>
412 void setState(const P1 & p1, const P2 & p2);
413
414 template<class S, class P1, class P2, class P3>
415 void setState(const P1 & p1, const P2 & p2, const P3 & p3);
416
417 template<class S, class P1, class P2, class P3, class P4>
418 void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4);
419
420 template<class S, class P1, class P2, class P3, class P4, class P5>
421 void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5);
422
423 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
424 void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6);
425
426 // Initiate transition to a state's history.
427 // If state has no history, transition is to the state itself.
428 template<class S>
429 void setStateHistory();
430
431 // Initiate transition to a new state.
432 // Parameter 'state' is the new state to enter.
433 // See above and class 'Alias' for more information.
434 void setState(const class Alias & state);
435
436 // Deprectated!
437 template<class S>
438 void setStateBox(typename S::Box * box = 0);
439
440 // Deprectated!
441 template<class S>
442 void setStateDirect(typename S::Box * box = 0);
443
444 // 'Restore from snapshot' event: set current state.
445 // Default implementation: Does not trigger entry actions!
446 virtual void _restore(_StateInstance & current);
447
448 // only to be used in _restore
449 void setState(_StateInstance & current);
450
451 // 'Shutdown machine' event: exit all states.
452 // Default implementation: Triggers exit actions!
453 // Override empty to omit calling exit actions.
454 virtual void _shutdown();
455
456 // This is the method to bubble up history information
457 // for states whose superstates have no history (so does nothing).
458 virtual void _setHistorySuper(_StateInstance & /* self */, _StateInstance & /* deep*/ ) {}
459
460 private:
461 // State exit. Not allowed to initiate state change.
462 virtual void exit() {}
463
464 // State entry. Not allowed to initiate state change.
465 virtual void entry() {}
466
467 // Special kind of state entry: Upon transition to a new state,
468 // entry methods of that state and its superstates are called;
469 // 'init' however is called only on the one state the transition
470 // actually goes to.
471 // Is allowed to change state (to child states).
472 virtual void init() {}
473
474 private:
475 // C++ needs something like package visibility
476
477 // for _myStateInstance
478 template<class T>
479 friend class TopBase;
480
481 // for _getInstance
482 template<class C, class P>
483 friend class Link;
484
485 friend class _StateInstance;
486 friend class _RootInstance;
487
488 friend class _MachineBase;
489
490 // Create StateInstance object of state.
491 static _StateInstance & _getInstance(_MachineBase & machine);
492
493 virtual void _deleteBox(_StateInstance & /* instance */) {}
494
495 // Default history strategy (no history).
496 virtual void _saveHistory(_StateInstance & /* self */, _StateInstance & /* shallow */, _StateInstance & /* deep */) {}
497
498 private:
499 _StateInstance & _myStateInstance;
500 };
501
502
504 // Base class for user defined top state (and indirectly all other states).
505 template<class T>
507 public:
508 // This typedef is an alias for user defined top state in all (sub)states.
509 using TOP = T;
510
511 protected:
513 : _StateSpecification(instance)
514 {}
515
516 void dispatch(IEvent<TOP> * event);
517
518 const Machine<TOP> & machine();
519 };
520
521
523 // This class links substate specifications to superstate specifications by
524 // deriving from the superstate and being derived from by the substate.
525 // Substates inherit event handlers from superstates for reuse or redefinition
526 // this way.
527 template<class C, class P>
528 class Link : public P {
529 public:
530 // Alias for superstate.
531 using SUPER = P;
532
533 // Alias for topstate.
534 using TOP = typename P::TOP;
535
536 // Default box type.
537 using Box = _EmptyBox;
538
539 // Get unique key of state.
540 static Key key();
541
542 static Alias alias();
543
544 static bool isChild(Key other) {
545 return key() == other || SUPER::isChild(other);
546 }
547
548 static bool isParent(Key other) {
549 return static_cast<_KeyData *>(other)->childPredicate(key());
550 }
551
552 // Is machine m in this state?
553 static bool isCurrent(const _MachineBase & machine);
554
555 // Deprecated!
556 // Is machine m in exactly this state?
557 static bool isCurrentDirect(const _MachineBase & machine);
558
559 static void clearHistory(const _MachineBase & machine);
560
561 static void clearHistoryDeep(const _MachineBase & machine);
562
563 static Alias history(const _MachineBase & machine);
564
565 protected:
566 // Needed to perform compile time checks.
568
569 Link(_StateInstance & instance);
570
571 // These definitions seem redundant but they are not!
572 // They override parent definitions so each substate gets either
573 // this default or their own, but never its parents definitions.
574 void entry() override {}
575 void init() override {}
576 void exit() override {}
577
578 // This method keeps '_myStateInstance' attribute private.
579 void * _box();
580
581 private:
582 // for _getInstance
583 template<class U, class V>
584 friend class Link;
585
586 // for _getInstance
588
589 // for _getInstance
590 friend class Machine<TOP>;
591
592 // for _getInstance
593 friend class Alias;
594
595 // for Tests
596 friend class ::TestAccess;
597
598 // Create StateInstance object of state.
599 static _StateInstance & _getInstance(_MachineBase & machine);
600
601 // Box is by default not persistent. Not redundant!
602 void _deleteBox(_StateInstance & instance) override;
603
604 // Default history strategy (no history). Not redundant!
605 void _saveHistory(_StateInstance & self, _StateInstance & /*shallow*/, _StateInstance & deep) override {
606 // Bubble up history. If no superstate has history, _setHistorySuper will do nothing.
607 this->_setHistorySuper(self, deep);
608 }
609
610 private:
611 _StateInstance & _myStateInstance;
612 };
613
614
616 // Unique identifier for state S.
617 template<class S>
618 class StateID {
619 public:
620 static const ID value;
621 };
622
623
625 // StateInstance maintains machine specific data about a state. Keeps history, box
626 // and state object for state. StateInstance object is created the first time state
627 // is entered. There is at most one StateInstance object per state per machine
628 // instance.
630 protected:
632
633 public:
635
636 // Perform entry actions.
637 // 'first' is true on very first call.
638 void entry(_StateInstance & previous, bool first = true);
639
640 // Perform exit actions.
641 void exit(_StateInstance & next);
642
643 // Perform init action.
644 void init(bool history);
645
646 void saveHistory(_StateInstance & shallow, _StateInstance & deep) {
647 // Check state's history strategy.
648 mySpecification->_saveHistory(*this, shallow, deep);
649 }
650
651 // Update superstate's history information:
653 if (myParent != nullptr)
654 // Let it choose between deep or shallow history.
655 myParent->saveHistory(*this, deep);
656 }
657
658#ifdef MACHO_SNAPSHOTS
659 // Copy state of another StateInstance object.
660 void copy(_StateInstance & original);
661
662 // Create a clone of StateInstance object for another machine.
663 _StateInstance * clone(_MachineBase & newMachine);
664#endif
665
666 void shutdown() {
668 }
669
670 void restore(_StateInstance & instance) {
671 mySpecification->_restore(instance);
672 }
673
674 virtual ID id() = 0;
675
676 virtual Key key() = 0;
677
678 virtual const char * name() = 0;
679
680 // 'Virtual constructor' needed for cloning.
682
683 virtual void createBox() = 0;
684 virtual void deleteBox() = 0;
685#ifdef MACHO_SNAPSHOTS
686 virtual void cloneBox(void * box) = 0;
687#endif
688
689 // Deprecated!
690 void setBox(void * box) {
691 assert(!myBox);
692
693 if (myBoxPlace != nullptr) {
694 // Free cached memory of previously used box.
695 ::operator delete(myBoxPlace);
696 myBoxPlace = nullptr;
697 }
698
699 myBox = box;
700 }
701
702 // Is 'instance' a superstate?
703 bool isChild(const _StateInstance & instance) {
704 return this == &instance || ((myParent != nullptr) && myParent->isChild(instance));
705 }
706
711
712 void * box() {
713 assert(myBox);
714 return myBox;
715 }
716
718 return myMachine;
719 }
720
721 // const: History can be manipulated even on a const object.
724 }
725
727 return myHistory;
728 }
729
730 protected:
732 _StateSpecification * mySpecification; // Instance of state class
735 void * myBox;
736 void * myBoxPlace; // Reused box heap memory
737 };
738
739
741 // StateInstance for Root state (the real top state).
743 protected:
745
751
752 public:
753 ID id() override {
754 return 0;
755 }
756
757 Key key() override {
758 // Can't happen: key is only called by users, and they don't know about Root.
759 assert(false); return nullptr;
760 }
761
762 void createBox() override {}
763 void deleteBox() override {}
764#ifdef MACHO_SNAPSHOTS
765 virtual void cloneBox(void * box) {}
766#endif
767
768 const char * name() override { return "Root"; }
769
770 // 'Virtual constructor' needed for cloning.
772 return new _RootInstance(machine, parent);
773 }
774
775 };
776
777
779 // StateInstance for substates (including Top ;-)
780 // Has methods to create state specific objects.
781 template<class S>
783 protected:
784 template<class C, class P>
785 friend class Link;
786
788 : _StateInstance(machine, parent)
789 {
790 assert(parent);
791 this->mySpecification = new S(*this);
792 }
793
794 public:
795 using Box = typename S::Box;
796
798 if (this->myBox)
800 }
801
802 const char * name() override { return S::_state_name(); }
803
804 ID id() override {
805 return StateID<S>::value;
806 }
807
808 Key key() override {
809 return S::key();
810 }
811
812 // 'Virtual constructor' needed for cloning.
814 return new _SubstateInstance<S>(machine, parent);
815 }
816
817 void createBox() override {
818 if (!this->myBox)
820 }
821
822 void deleteBox() override {
823 assert(myBox);
825 }
826
827#ifdef MACHO_SNAPSHOTS
828 virtual void cloneBox(void * box) {
829 assert(!myBox);
830 assert(!myBoxPlace);
831 // Needs copy constructor in ALL box types.
832 myBox = Macho::_cloneBox<Box>(box);
833 }
834#endif
835
836 };
837
838
840 // Definitions for queuable event types
841
842 // Generic interface for event objects (available only to MachineBase)
844 public:
845 virtual ~_IEventBase() = default;
846 virtual void dispatch(_StateInstance &) = 0;
847 };
848
849
850 // Interface for event objects (bound to a top state)
851 template<class TOP>
852 class IEvent : protected _IEventBase {
853 friend class Machine<TOP>;
854 friend class TopBase<TOP>;
855 };
856
857
858 // Event with four parameters
859 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5, class P6>
860 class _Event6 : public IEvent<TOP> {
861 using Signature = R (TOP::*)(P1, P2, P3, P4, P5, P6);
862
863 public:
864 _Event6(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6)
865 : myHandler(handler)
866 , myParam1(p1)
867 , myParam2(p2)
868 , myParam3(p3)
869 , myParam4(p4)
870 , myParam5(p5)
871 , myParam6(p6)
872 {}
873
874 protected:
875 void dispatch(_StateInstance & instance) {
876 TOP & behaviour = static_cast<TOP &>(instance.specification());
878 }
879
880 Signature myHandler;
887 };
888
889
890 // Event with four parameters
891 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5>
892 class _Event5 : public IEvent<TOP> {
893 using Signature = R (TOP::*)(P1, P2, P3, P4, P5);
894
895 public:
896 _Event5(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5)
897 : myHandler(handler)
898 , myParam1(p1)
899 , myParam2(p2)
900 , myParam3(p3)
901 , myParam4(p4)
902 , myParam5(p5)
903 {}
904
905 protected:
906 void dispatch(_StateInstance & instance) {
907 TOP & behaviour = static_cast<TOP &>(instance.specification());
909 }
910
911 Signature myHandler;
917 };
918
919
920 // Event with four parameters
921 template<class TOP, class R, class P1, class P2, class P3, class P4>
922 class _Event4 : public IEvent<TOP> {
923 using Signature = R (TOP::*)(P1, P2, P3, P4);
924
925 public:
926 _Event4(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4)
927 : myHandler(handler)
928 , myParam1(p1)
929 , myParam2(p2)
930 , myParam3(p3)
931 , myParam4(p4)
932 {}
933
934 protected:
935 void dispatch(_StateInstance & instance) {
936 TOP & behaviour = static_cast<TOP &>(instance.specification());
938 }
939
940 Signature myHandler;
945 };
946
947
948 // Event with three parameters
949 template<class TOP, class R, class P1, class P2, class P3>
950 class _Event3 : public IEvent<TOP> {
951 using Signature = R (TOP::*)(P1, P2, P3);
952
953 public:
954 _Event3(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3)
955 : myHandler(handler)
956 , myParam1(p1)
957 , myParam2(p2)
958 , myParam3(p3)
959 {}
960
961 protected:
962 void dispatch(_StateInstance & instance) {
963 TOP & behaviour = static_cast<TOP &>(instance.specification());
964 (behaviour.*myHandler)(myParam1, myParam2, myParam3);
965 }
966
967 Signature myHandler;
971 };
972
973
974 // Event with two parameters
975 template<class TOP, class R, class P1, class P2>
976 class _Event2 : public IEvent<TOP> {
977 using Signature = R (TOP::*)(P1, P2);
978
979 public:
980 _Event2(Signature handler, const P1 & p1, const P2 & p2)
981 : myHandler(handler)
982 , myParam1(p1)
983 , myParam2(p2)
984 {}
985
986 protected:
987 void dispatch(_StateInstance & instance) {
988 TOP & behaviour = static_cast<TOP &>(instance.specification());
989 (behaviour.*myHandler)(myParam1, myParam2);
990 }
991
992 Signature myHandler;
995 };
996
997
998 // Event with one parameter
999 template<class TOP, class R, class P1>
1000 class _Event1 : public IEvent<TOP> {
1001 using Signature = R (TOP::*)(P1);
1002
1003 public:
1004 _Event1(Signature handler, const P1 & p1)
1005 : myHandler(handler)
1006 , myParam1(p1)
1007 {}
1008
1009 protected:
1010 void dispatch(_StateInstance & instance) override {
1011 TOP & behaviour = static_cast<TOP &>(instance.specification());
1012 (behaviour.*myHandler)(myParam1);
1013 }
1014
1015 Signature myHandler;
1017 };
1018
1019
1020 // Event with no parameters
1021 template<class TOP, class R>
1022 class _Event0 : public IEvent<TOP> {
1023 using Signature = R (TOP::*)();
1024
1025 public:
1026 _Event0(Signature handler)
1027 : myHandler(handler)
1028 {}
1029
1030 protected:
1031 void dispatch(_StateInstance & instance) override {
1032 TOP & behaviour = static_cast<TOP &>(instance.specification());
1033 (behaviour.*myHandler)();
1034 }
1035
1036 Signature myHandler;
1037 };
1038
1039
1040 // Event creating functions using type inference
1041 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5, class P6>
1042 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4, P5, P6), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
1043 return new _Event6<TOP, R, P1, P2, P3, P4, P5, P6>(handler, p1, p2, p3, p4, p5, p6);
1044 }
1045
1046 // Event creating functions using type inference
1047 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5>
1048 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4, P5), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1049 return new _Event5<TOP, R, P1, P2, P3, P4, P5>(handler, p1, p2, p3, p4, p5);
1050 }
1051
1052 // Event creating functions using type inference
1053 template<class TOP, class R, class P1, class P2, class P3, class P4>
1054 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1055 return new _Event4<TOP, R, P1, P2, P3, P4>(handler, p1, p2, p3, p4);
1056 }
1057
1058 template<class TOP, class R, class P1, class P2, class P3>
1059 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3), const P1 & p1, const P2 & p2, const P3 & p3) {
1060 return new _Event3<TOP, R, P1, P2, P3>(handler, p1, p2, p3);
1061 }
1062
1063 template<class TOP, class R, class P1, class P2>
1064 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2), const P1 & p1, const P2 & p2) {
1065 return new _Event2<TOP, R, P1, P2>(handler, p1, p2);
1066 }
1067
1068 template<class TOP, class R, class P1>
1069 inline IEvent<TOP> * Event(R (TOP::*handler)(P1), const P1 & p1) {
1070 return new _Event1<TOP, R, P1>(handler, p1);
1071 }
1072
1073 template<class TOP, class R>
1074 inline IEvent<TOP> * Event(R (TOP::*handler)()) {
1075 return new _Event0<TOP, R>(handler);
1076 }
1077
1078} // namespace Macho
1079
1080
1082// MSVC++ 8.0 does not handle qualified member template friends
1083// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101615
1084// Otherwise call could happen directly in Initializer classes.
1086public:
1087 template<class S, class P1>
1088 static inline void execute(Macho::_StateInstance & instance, const P1 & p1) {
1089 S & behaviour = static_cast<S &>(instance.specification());
1090 behaviour.init(p1);
1091 }
1092
1093 template<class S, class P1, class P2>
1094 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2) {
1095 S & behaviour = static_cast<S &>(instance.specification());
1096 behaviour.init(p1, p2);
1097 }
1098
1099 template<class S, class P1, class P2, class P3>
1100 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3) {
1101 S & behaviour = static_cast<S &>(instance.specification());
1102 behaviour.init(p1, p2, p3);
1103 }
1104
1105 template<class S, class P1, class P2, class P3, class P4>
1106 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1107 S & behaviour = static_cast<S &>(instance.specification());
1108 behaviour.init(p1, p2, p3, p4);
1109 }
1110
1111 template<class S, class P1, class P2, class P3, class P4, class P5>
1112 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1113 S & behaviour = static_cast<S &>(instance.specification());
1114 behaviour.init(p1, p2, p3, p4, p5);
1115 }
1116
1117 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1118 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
1119 S & behaviour = static_cast<S &>(instance.specification());
1120 behaviour.init(p1, p2, p3, p4, p5, p6);
1121 }
1122
1123};
1124
1125
1127namespace Macho {
1128
1130 // Base class for state initializers.
1131 // Initializer are used to provide parameters to states.
1132 // The 'execute' method of Initializers will call a state's init method with
1133 // the data of the initializer object.
1135 public:
1136 virtual ~_Initializer() = default;
1137
1138 // Create copy of initializer.
1139 virtual _Initializer * clone() = 0;
1140
1141 // Deallocate object.
1142 virtual void destroy() { delete this; }
1143
1144 virtual Key adapt(Key key) { return key; }
1145
1146 // Initialize given state. State is new current state of a state machine.
1147 virtual void execute(_StateInstance & instance) = 0;
1148 };
1149
1150
1151 // Base class for Singleton initializers.
1153 // Copy of Singleton is Singleton.
1154 _Initializer * clone() override { return this; }
1155
1156 // Singletons are never destroyed.
1157 void destroy() override {}
1158 };
1159
1160
1161 // Default initializer: provides no parameters, calls state's 'init' method
1162 // only.
1164 public:
1165 void execute(_StateInstance & instance) override {
1166 instance.init(false);
1167 }
1168 };
1169
1170
1171 // History initializer: provides no parameters, performs transition to
1172 // history of state if available.
1174 public:
1175 void execute(_StateInstance & instance) override {
1176 instance.init(true);
1177 }
1178 };
1179
1180
1181 // Special initializer: Helps alias impersonate as history state of given state.
1183 public:
1184 _AdaptingInitializer(const _MachineBase & machine) : myMachine(machine) {}
1185
1186 void execute(_StateInstance & instance) override {
1187 instance.init(true);
1188 }
1189
1190 _Initializer * clone() override {
1191 return new _AdaptingInitializer(myMachine);
1192 }
1193
1194 Key adapt(Key key) override;
1195
1196 protected:
1198 };
1199
1200
1201 // Initializers with one to six parameters.
1202 template<class S, class P1>
1204 public:
1205 _Initializer1(const P1 & p1)
1206 : myParam1(p1)
1207 {}
1208
1209 _Initializer * clone() override {
1210 return new _Initializer1<S, P1>(myParam1);
1211 }
1212
1213 void execute(_StateInstance & instance) override {
1215 delete this;
1216 }
1217
1219 };
1220
1221
1222 template<class S, class P1, class P2>
1224 public:
1225 _Initializer2(const P1 & p1, const P2 & p2)
1226 : myParam1(p1)
1227 , myParam2(p2)
1228 {}
1229
1230 _Initializer * clone() override {
1232 }
1233
1234 void execute(_StateInstance & instance) override {
1236 delete this;
1237 }
1238
1241 };
1242
1243
1244 template<class S, class P1, class P2, class P3>
1246 public:
1247 _Initializer3(const P1 & p1, const P2 & p2, const P3 & p3)
1248 : myParam1(p1)
1249 , myParam2(p2)
1250 , myParam3(p3)
1251 {}
1252
1256
1257 void execute(_StateInstance & instance) override {
1259 delete this;
1260 }
1261
1265 };
1266
1267
1268 template<class S, class P1, class P2, class P3, class P4>
1270 public:
1271 _Initializer4(const P1 & p1, const P2 & p2, const P3 & p3, P4 & p4)
1272 : myParam1(p1)
1273 , myParam2(p2)
1274 , myParam3(p3)
1275 , myParam4(p4)
1276 {}
1277
1281
1282 void execute(_StateInstance & instance) override {
1284 delete this;
1285 }
1286
1291 };
1292
1293
1294 template<class S, class P1, class P2, class P3, class P4, class P5>
1296 public:
1297 _Initializer5(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5)
1298 : myParam1(p1)
1299 , myParam2(p2)
1300 , myParam3(p3)
1301 , myParam4(p4)
1302 , myParam5(p5)
1303 {}
1304
1308
1309 void execute(_StateInstance & instance) override {
1311 delete this;
1312 }
1313
1319 };
1320
1321
1322 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1324 public:
1325 _Initializer6(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6)
1326 : myParam1(p1)
1327 , myParam2(p2)
1328 , myParam3(p3)
1329 , myParam4(p4)
1330 , myParam5(p5)
1331 , myParam6(p6)
1332 {}
1333
1337
1338 void execute(_StateInstance & instance) override {
1340 delete this;
1341 }
1342
1349 };
1350
1351
1353 // Singleton initializers.
1356
1357
1359 // Base class for Machine objects.
1361 public:
1362 class Alias currentState() const;
1363
1364 protected:
1366 virtual ~_MachineBase();
1367
1368 // Transition to new state.
1369 void setState(_StateInstance & instance, _Initializer * init);
1370
1371 // Transition to new state specified by state alias.
1372 void setState(const Alias & state);
1373
1374 // Prepare transition to new state (performed on call to 'rattleOn').
1375 // There can be only one state transition pending (asserts otherwise)!
1376 // 'init' is an initializer for the new state.
1378 assert( (!myPendingState || myPendingState == &instance) &&
1379 "There is already a state transition pending!");
1380
1381 myPendingState = &instance;
1382 myPendingInit = init;
1383 }
1384
1385 // Provide event object to be executed on current state.
1387 assert(event);
1388 assert(!myPendingEvent && "There is already an event pending!");
1389
1390 myPendingEvent = event;
1391 }
1392
1393 // Performs pending state transition.
1394 void rattleOn();
1395
1396 // Get StateInstance object for ID.
1398 return myInstances[id];
1399 }
1400
1401 // Get StateInstance object for ID.
1402 const _StateInstance * getInstance(ID id) const {
1403 return myInstances[id];
1404 }
1405
1406 // Starts the machine with the specified start state.
1407 void start(_StateInstance & instance);
1408 void start(const Alias & state);
1409
1410 // Shuts machine down. Will exit any states and free all allocated
1411 // resources.
1412 void shutdown();
1413
1414 // Allocate space for pointers to StateInstance objects.
1415 void allocate(unsigned int count);
1416
1417 // Free all StateInstance objects.
1418 void free(unsigned int count);
1419
1420 // const: History can be manipulated even on a const machine.
1421 void clearHistoryDeep(unsigned int count, const _StateInstance & instance) const;
1422
1423#ifdef MACHO_SNAPSHOTS
1424 // Create a copy of another machines StateInstance objects (includes boxes).
1425 void copy(_StateInstance ** other, unsigned int count);
1426
1427 // Create a copy of another machines StateInstance object.
1428 _StateInstance * createClone(ID id, _StateInstance * original);
1429#endif
1430
1431 protected:
1432 // C++ needs something like package visibility
1433
1434 // for getInstance
1435 template<class C, class P>
1436 friend class Link;
1437
1438 // for setPendingEvent
1439 template<class T>
1440 friend class TopBase;
1441
1442 // for getInstance
1444
1445 // for getInstance
1446 friend class Alias;
1447
1448 // for getInstance
1450
1451 // for setPendingState
1452 friend class _StateInstance;
1453
1454 // for Tests
1455 friend class ::TestAccess;
1456
1457 // Current state of Machine object.
1459
1460 // Information about pending state transition.
1463
1464 // Deprecated!
1465 void * myPendingBox{nullptr};
1466
1468
1469 // Array of StateInstance objects.
1471 };
1472
1473
1475 // This is the base class for state aliases. A state alias represents a
1476 // state of a machine. A transition to that state can be initiated by
1477 // giving the alias object to the 'setState' method.
1478 //
1479 // State aliases are created by the template functions 'State' further below.
1480 // Parameters can be provided to these functions that will be used to
1481 // initialize the state on transition to it.
1482 class Alias {
1483 public:
1484 Alias(Key key, bool history = false)
1485 : myStateKey(key)
1486 , myInitializer(
1487 history ?
1488 static_cast<_Initializer *>(&_theHistoryInitializer)
1489 :
1490 static_cast<_Initializer *>(&_theDefaultInitializer)
1491 )
1492 {
1493 assert(key);
1494 }
1495
1497 : myStateKey(key)
1498 , myInitializer(init)
1499 {
1500 assert(key);
1501 }
1502
1503 Alias(const Alias & other)
1504 : myStateKey(other.myStateKey)
1505 , myInitializer(other.myInitializer->clone())
1506 {}
1507
1508 Alias & operator=(const Alias & other) {
1509 if (this == &other) return *this;
1510
1512
1513 myStateKey = other.myStateKey;
1515
1516 return *this;
1517 }
1518
1521 }
1522
1523 // Use this to test validity: zero means invalid alias.
1524 operator Key() const {
1525 return key();
1526 }
1527
1528 bool isChild(Key k) const {
1529 return key()->childPredicate(k);
1530 }
1531
1532 bool isParent(Key k) const {
1533 return static_cast<_KeyData *>(k)->childPredicate(key());
1534 }
1535
1536 const char * name() const {
1537 return key()->name();
1538 }
1539
1540 ID id() const {
1541 return key()->id;
1542 }
1543
1544 protected:
1545 friend class _MachineBase;
1547
1548 void setState(_MachineBase & machine) const;
1549
1550 _KeyData * key() const { return static_cast<_KeyData *>(myInitializer->adapt(myStateKey)); }
1551
1552 protected:
1553 // Key of specified state.
1555
1556 // Initializer of this alias.
1558 };
1559
1560 // Deprecated!
1562
1563
1564 // Create alias with 0 to 6 parameters.
1565 template<class S>
1567 return Alias(S::key());
1568 }
1569
1570 template<class S, class P1>
1571 Alias State(const P1 & p1) {
1572 return Alias(S::key(), new _Initializer1<S, P1>(p1));
1573 }
1574
1575 template<class S, class P1, class P2>
1576 Alias State(const P1 & p1, const P2 & p2) {
1577 return Alias(S::key(), new _Initializer2<S, P1, P2>(p1, p2));
1578 }
1579
1580 template<class S, class P1, class P2, class P3>
1581 Alias State(const P1 & p1, const P2 & p2, const P3 & p3) {
1582 return Alias(S::key(), new _Initializer3<S, P1, P2, P3>(p1, p2, p3));
1583 }
1584
1585 template<class S, class P1, class P2, class P3, class P4>
1586 Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1587 return Alias(S::key(), new _Initializer4<S, P1, P2, P3, P4>(p1, p2, p3, p4));
1588 }
1589
1590 template<class S, class P1, class P2, class P3, class P4, class P5>
1591 Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1592 return Alias(S::key(), new _Initializer5<S, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5));
1593 }
1594
1595 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1596 Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
1597 return Alias(S::key(), new _Initializer6<S, P1, P2, P3, P4, P5, P6>(p1, p2, p3, p4, p5, p6));
1598 }
1599
1600 // Create alias for state's history: not the current history state, but
1601 // really the history of a state. This means that the alias may point to
1602 // different states during its life. Needs a machine instance to take history from.
1603 template<class S>
1605 return Alias(S::key(), new _AdaptingInitializer(machine));
1606 }
1607
1608
1610 // Snapshot of a machine object.
1611 // Saves the state of a machine object at a specific point in time to be restored
1612 // later (can be used to achieve something like backtracking).
1613 // Includes boxes of current state and persistent boxes.
1614 // Assign a snapshot to a machine (operator=) to restore state.
1615 // Note that no exit/entry actions of the overwritten machine state are performed!
1616 // Box destructors however are executed!
1617#ifdef MACHO_SNAPSHOTS
1618 template<class TOP>
1619 class Snapshot : public _MachineBase {
1620 public:
1621 Snapshot(Machine<TOP> & machine);
1622
1623 ~Snapshot() {
1624 free(Machine<TOP>::theStateCount);
1625 }
1626
1627 private:
1628 friend class Machine<TOP>;
1629
1630 Snapshot(const Snapshot<TOP> & other);
1631 Snapshot & operator=(const Snapshot<TOP> & other);
1632 };
1633#endif
1634
1635
1637 // A Machine object maintains a current state.
1638 // The state can be any substate of template parameter TOP.
1639 // TOP is the Machine's top most and inital state. TOP must be defined by
1640 // the macro TOPSTATE. Event processing is done by calling methods (event
1641 // handlers) on the current state.
1642 // This is realized by defining an arrow ('->') operator on Machine,
1643 // forwarding to the interface of TOP.
1644 // Every possible event handler to be called must therefore appear in the
1645 // interface of TOP. Events are dispatched by using this operator on a
1646 // Machine object (e.g. 'machine->event()').
1647 template<class TOP>
1648 class Machine : public _MachineBase {
1649 public:
1650
1651 // This class performs an action in its destructor after an event
1652 // handler has finished. Comparable to an After Advice in AOP.
1654 AfterAdvice(Machine<TOP> & m) : myMachine(m) {}
1655
1656 // Event handler has finished execution. Execute pending transitions now.
1657 ~AfterAdvice() { myMachine.rattleOn(); }
1658
1659 // this arrow operator finally dispatches to TOP interface.
1660 TOP * operator->() {
1661 return static_cast<TOP *>(& (myMachine.myCurrentState->specification()) );
1662 }
1663
1664 private:
1665 Machine<TOP> & myMachine;
1666 };
1667
1669 // Compile time check: TOP must directly derive from TopBase<TOP>
1670 using MustDeriveFromTopBase = typename CheckSameType<TopBase<TOP>, typename TOP::SUPER>::Check;
1671 // suppress unused-typdefs warnig
1672 static_assert(static_cast<MustDeriveFromTopBase*>(nullptr)==nullptr, "dummy");
1673
1674 allocate(theStateCount);
1675 start(TOP::_getInstance(*this));
1676 }
1677
1678 // Initialize with a state alias object to have machine go to a state
1679 // other than TOP on startup.
1680 Machine(const Alias & state) {
1681 // Compile time check: TOP must directly derive from TopBase<TOP>
1682 using MustDeriveFromTopBase = typename CheckSameType<TopBase<TOP>, typename TOP::SUPER>::Check;
1683 // suppress unused-typdefs warnig
1684 static_assert(static_cast<MustDeriveFromTopBase*>(nullptr)==nullptr, "dummy");
1685
1686 allocate(theStateCount);
1687 start(state);
1688 }
1689
1690#ifdef MACHO_SNAPSHOTS
1691 // Create machine from a snapshot.
1692 Machine(const Snapshot<TOP> & snapshot) {
1693 allocate(theStateCount);
1694 copy(snapshot.myInstances, theStateCount);
1695 }
1696
1697 // Overwrite current machine state by snapshot.
1698 Machine<TOP> & operator=(const Snapshot<TOP> & snapshot) {
1699 assert(!myPendingState);
1700 assert(!myPendingEvent);
1701
1703
1704 free(theStateCount);
1705 copy(snapshot.myInstances, theStateCount);
1706
1707 // Go to Root state first
1709
1710 // Then set previous current state
1711 _StateInstance * current = getInstance(snapshot.myCurrentState->id());
1712 current->restore(*current);
1713 rattleOn();
1714
1715 return *this;
1716 }
1717#endif
1718
1719 ~Machine() override {
1721 free(theStateCount);
1722 }
1723
1724 // Don't return pointer to interface right now: we need to know when the
1725 // event handler has finished; return an AfterAdvice object instead:
1726 // it allows us to perform actions after access.
1728 assert(myCurrentState);
1729 assert(!myPendingState);
1730
1731 // We need to know when the event handler has finished.
1732 return AfterAdvice(*this);
1733 }
1734
1735 // Dispatch an event object to machine.
1736 void dispatch(IEvent<TOP> * event, bool destroy = true) {
1737 assert(event);
1738
1739 event->dispatch(*myCurrentState);
1740 if (destroy) delete event;
1741
1742 rattleOn();
1743 }
1744
1745 // Allow (const) access to top state's box (for state data extraction).
1746 const typename TOP::Box & box() const {
1747 assert(myCurrentState);
1748 return static_cast<TOP &>(myCurrentState->specification()).TOP::box();
1749 }
1750
1751 private:
1752 template<class C, class P>
1753 friend class Link;
1754
1755 private:
1756 Machine(const Machine<TOP> & other) = delete;
1757 Machine<TOP> & operator=(const Machine<TOP> & other) = delete;
1758
1759#ifdef MACHO_SNAPSHOTS
1760 friend class Snapshot<TOP>;
1761#endif
1762
1763 template<class T> friend class StateID;
1764
1765 // Next free identifier for StateInstance objects.
1766 static ID theStateCount;
1767 };
1768
1769 // Root is always there and has ID 0, so start from 1
1770 template<class TOP>
1772
1773 // Each state has a unique ID number.
1774 // The identifiers are consecutive integers starting from zero,
1775 // which allows use as index into a vector for fast access.
1776 // 'Root' always has zero as id.
1777 //template<class S>
1778 //const ID StateID<S>::value = Machine<typename S::TOP>::theStateCount++;
1779
1780
1782 // Implementation for StateSpecification
1783
1784 // Initiate state transition with 0 to six parameters.
1785 template<class S>
1787 _MachineBase & m = _myStateInstance.machine();
1788 _StateInstance & instance = S::_getInstance(m);
1790 }
1791
1792 template<class S, class P1>
1793 inline void _StateSpecification::setState(const P1 & p1) {
1794 _MachineBase & m = _myStateInstance.machine();
1795 _StateInstance & instance = S::_getInstance(m);
1796 m.setPendingState(instance, new _Initializer1<S, P1>(p1));
1797 }
1798
1799 template<class S, class P1, class P2>
1800 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2) {
1801 _MachineBase & m = _myStateInstance.machine();
1802 _StateInstance & instance = S::_getInstance(m);
1803 m.setPendingState(instance, new _Initializer2<S, P1, P2>(p1, p2));
1804 }
1805
1806 template<class S, class P1, class P2, class P3>
1807 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3) {
1808 _MachineBase & m = _myStateInstance.machine();
1809 _StateInstance & instance = S::_getInstance(m);
1810 m.setPendingState(instance, new _Initializer3<S, P1, P2, P3>(p1, p2, p3));
1811 }
1812
1813 template<class S, class P1, class P2, class P3, class P4>
1814 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1815 _MachineBase & m = _myStateInstance.machine();
1816 _StateInstance & instance = S::_getInstance(m);
1817 m.setPendingState(instance, new _Initializer4<S, P1, P2, P3, P4>(p1, p2, p3, p4));
1818 }
1819
1820 template<class S, class P1, class P2, class P3, class P4, class P5>
1821 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1822 _MachineBase & m = _myStateInstance.machine();
1823 _StateInstance & instance = S::_getInstance(m);
1824 m.setPendingState(instance, new _Initializer5<S, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5));
1825 }
1826
1827 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1828 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
1829 _MachineBase & m = _myStateInstance.machine();
1830 _StateInstance & instance = S::_getInstance(m);
1831 m.setPendingState(instance, new _Initializer6<S, P1, P2, P3, P4, P5, P6>(p1, p2, p3, p4, p5, p6));
1832 }
1833
1834 // Initiate state transition to a state's history.
1835 template<class S>
1837 _MachineBase & m = _myStateInstance.machine();
1838 _StateInstance & instance = S::_getInstance(m);
1840 }
1841
1842 // Deprecated!
1843 template<class S>
1844 inline void _StateSpecification::setStateBox(typename S::Box * box) {
1845 _MachineBase & m = _myStateInstance.machine();
1846 _StateInstance & instance = S::_getInstance(m);
1847 m.myPendingBox = box;
1849 }
1850
1851 // Deprecated!
1852 template<class S>
1853 inline void _StateSpecification::setStateDirect(typename S::Box * box) {
1854 _MachineBase & m = _myStateInstance.machine();
1855 _StateInstance & instance = S::_getInstance(m);
1856 m.myPendingBox = box;
1858 }
1859
1860
1862 // Implementation for TopBase
1863 template<class T>
1864 inline void TopBase<T>::dispatch(IEvent<TOP> * event) {
1865 assert(event);
1866 _myStateInstance.machine().setPendingEvent(event);
1867 }
1868
1869 template<class T>
1870 // Returns current state machine instance.
1872 return static_cast<Machine<TOP> &>(this->_myStateInstance.machine());
1873 }
1874
1875
1877 // Implementation for Link
1878 template<class C, class P>
1880 : P(P::_getInstance(instance.machine()))
1881 // Can't initialize _myStateInstance with _getInstance,
1882 // because this would result in an endless loop (at least for first call)
1883 , _myStateInstance(instance)
1884 {}
1885
1886 // This method keeps '_myStateInstance' attribute private.
1887 template<class C, class P>
1888 inline void * Link<C, P>::_box() {
1889 return _myStateInstance.box();
1890 }
1891
1892 // Default behaviour: free box on exit.
1893 template<class C, class P>
1894 inline void Link<C, P>::_deleteBox(_StateInstance & instance) {
1895 instance.deleteBox();
1896 }
1897
1898 // Create StateInstance object of state.
1899 template<class C, class P>
1900 /* static */ inline _StateInstance & Link<C, P>::_getInstance(_MachineBase & machine) {
1901 // Look first in machine for existing StateInstance.
1902 _StateInstance * & instance = machine.getInstance(StateID<C>::value);
1903 if (instance == nullptr)
1904 // Will create parent StateInstance object if not already created.
1905 instance = new _SubstateInstance<C>(machine, &P::_getInstance(machine));
1906
1907 return *instance;
1908 }
1909
1910 template<class C, class P>
1911 /* static */ inline bool Link<C, P>::isCurrent(const _MachineBase & machine) {
1912 return machine.currentState().isChild(key());
1913 }
1914
1915 // Deprecated!
1916 template<class C, class P>
1917 /* static */ inline bool Link<C, P>::isCurrentDirect(const _MachineBase & machine) {
1918 return key() == machine.currentState();
1919 }
1920
1921 template<class C, class P>
1922 /* static */ void Link<C, P>::clearHistory(const _MachineBase & machine) {
1923 const _StateInstance * instance = machine.getInstance(StateID<C>::value);
1924 if (instance != nullptr)
1925 instance->setHistory(nullptr);
1926 }
1927
1928 template<class C, class P>
1929 /* static */ void Link<C, P>::clearHistoryDeep(const _MachineBase & machine) {
1930 const _StateInstance * instance = machine.getInstance(StateID<C>::value);
1931 if (instance != nullptr)
1933 }
1934
1935 template<class C, class P>
1936 /* static */ Alias Link<C, P>::history(const _MachineBase & machine) {
1937 const _StateInstance * instance = machine.getInstance(StateID<C>::value);
1938 _StateInstance * history = nullptr;
1939
1940 if (instance != nullptr)
1941 history = instance->history();
1942
1943 return history != nullptr ? history->key() : key();
1944 }
1945
1946 template<class C, class P>
1947 /* static */ inline Key Link<C, P>::key() {
1948 static _KeyData k = { _getInstance, isChild, C::_state_name, StateID<C>::value };
1949 return &k;
1950 }
1951
1952 template<class C, class P>
1953 /* static */ inline Alias Link<C, P>::alias() {
1954 return Alias(key());
1955 }
1956
1957
1959 // Implementation for Snapshot
1960#ifdef MACHO_SNAPSHOTS
1961 template<class TOP>
1962 Snapshot<TOP>::Snapshot(Machine<TOP> & machine) {
1963 assert(!machine.myPendingState);
1964 assert(!machine.myPendingEvent);
1965 assert(machine.myCurrentState);
1966
1969
1970 myCurrentState = getInstance(machine.myCurrentState->id());
1971 }
1972#endif
1973
1974} // namespace Macho
1975
1976
1977#endif // MACHO_HPP
Definition Macho.h:1482
_KeyData * key() const
Definition Macho.h:1550
Alias & operator=(const Alias &other)
Definition Macho.h:1508
Key myStateKey
Definition Macho.h:1554
bool isChild(Key k) const
Definition Macho.h:1528
~Alias()
Definition Macho.h:1519
Alias(Key key, _Initializer *init)
Definition Macho.h:1496
_Initializer * myInitializer
Definition Macho.h:1557
void setState(_MachineBase &machine) const
Alias(const Alias &other)
Definition Macho.h:1503
ID id() const
Definition Macho.h:1540
bool isParent(Key k) const
Definition Macho.h:1532
const char * name() const
Definition Macho.h:1536
Alias(Key key, bool history=false)
Definition Macho.h:1484
Definition Macho.h:852
Definition Macho.h:1648
Machine()
Definition Macho.h:1668
~Machine() override
Definition Macho.h:1719
void dispatch(IEvent< TOP > *event, bool destroy=true)
Definition Macho.h:1736
const TOP::Box & box() const
Definition Macho.h:1746
AfterAdvice operator->()
Definition Macho.h:1727
Machine(const Alias &state)
Definition Macho.h:1680
Definition Macho.h:618
static const ID value
Definition Macho.h:620
Definition Macho.h:506
T TOP
Definition Macho.h:509
TopBase(_StateInstance &instance)
Definition Macho.h:512
void dispatch(IEvent< TOP > *event)
Definition Macho.h:1864
const Machine< TOP > & machine()
Definition Macho.h:1871
Definition Macho.h:1182
_Initializer * clone() override
Definition Macho.h:1190
const _MachineBase & myMachine
Definition Macho.h:1197
_AdaptingInitializer(const _MachineBase &machine)
Definition Macho.h:1184
void execute(_StateInstance &instance) override
Definition Macho.h:1186
Key adapt(Key key) override
Definition Macho.h:1163
void execute(_StateInstance &instance) override
Definition Macho.h:1165
Definition Macho.h:311
static _EmptyBox theEmptyBox
Definition Macho.h:313
Definition Macho.h:1022
void dispatch(_StateInstance &instance) override
Definition Macho.h:1031
_Event0(Signature handler)
Definition Macho.h:1026
Signature myHandler
Definition Macho.h:1036
Definition Macho.h:1000
Signature myHandler
Definition Macho.h:1015
_Event1(Signature handler, const P1 &p1)
Definition Macho.h:1004
P1 myParam1
Definition Macho.h:1016
void dispatch(_StateInstance &instance) override
Definition Macho.h:1010
Definition Macho.h:976
P1 myParam1
Definition Macho.h:993
P2 myParam2
Definition Macho.h:994
_Event2(Signature handler, const P1 &p1, const P2 &p2)
Definition Macho.h:980
Signature myHandler
Definition Macho.h:992
void dispatch(_StateInstance &instance)
Definition Macho.h:987
Definition Macho.h:950
P3 myParam3
Definition Macho.h:970
_Event3(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3)
Definition Macho.h:954
P1 myParam1
Definition Macho.h:968
Signature myHandler
Definition Macho.h:967
void dispatch(_StateInstance &instance)
Definition Macho.h:962
P2 myParam2
Definition Macho.h:969
Definition Macho.h:922
void dispatch(_StateInstance &instance)
Definition Macho.h:935
_Event4(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
Definition Macho.h:926
P4 myParam4
Definition Macho.h:944
P2 myParam2
Definition Macho.h:942
P1 myParam1
Definition Macho.h:941
Signature myHandler
Definition Macho.h:940
P3 myParam3
Definition Macho.h:943
Definition Macho.h:892
P1 myParam1
Definition Macho.h:912
P2 myParam2
Definition Macho.h:913
P4 myParam4
Definition Macho.h:915
Signature myHandler
Definition Macho.h:911
_Event5(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
Definition Macho.h:896
P5 myParam5
Definition Macho.h:916
P3 myParam3
Definition Macho.h:914
void dispatch(_StateInstance &instance)
Definition Macho.h:906
Definition Macho.h:860
void dispatch(_StateInstance &instance)
Definition Macho.h:875
_Event6(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
Definition Macho.h:864
P3 myParam3
Definition Macho.h:883
P4 myParam4
Definition Macho.h:884
P1 myParam1
Definition Macho.h:881
P6 myParam6
Definition Macho.h:886
Signature myHandler
Definition Macho.h:880
P5 myParam5
Definition Macho.h:885
P2 myParam2
Definition Macho.h:882
Definition Macho.h:1173
void execute(_StateInstance &instance) override
Definition Macho.h:1175
Definition Macho.h:843
virtual void dispatch(_StateInstance &)=0
virtual ~_IEventBase()=default
Definition Macho.h:1203
void execute(_StateInstance &instance) override
Definition Macho.h:1213
P1 myParam1
Definition Macho.h:1218
_Initializer * clone() override
Definition Macho.h:1209
_Initializer1(const P1 &p1)
Definition Macho.h:1205
Definition Macho.h:1223
_Initializer2(const P1 &p1, const P2 &p2)
Definition Macho.h:1225
_Initializer * clone() override
Definition Macho.h:1230
void execute(_StateInstance &instance) override
Definition Macho.h:1234
P1 myParam1
Definition Macho.h:1239
P2 myParam2
Definition Macho.h:1240
Definition Macho.h:1245
P1 myParam1
Definition Macho.h:1262
P2 myParam2
Definition Macho.h:1263
_Initializer * clone() override
Definition Macho.h:1253
_Initializer3(const P1 &p1, const P2 &p2, const P3 &p3)
Definition Macho.h:1247
void execute(_StateInstance &instance) override
Definition Macho.h:1257
P3 myParam3
Definition Macho.h:1264
Definition Macho.h:1269
_Initializer * clone() override
Definition Macho.h:1278
P3 myParam3
Definition Macho.h:1289
_Initializer4(const P1 &p1, const P2 &p2, const P3 &p3, P4 &p4)
Definition Macho.h:1271
P1 myParam1
Definition Macho.h:1287
P2 myParam2
Definition Macho.h:1288
P4 myParam4
Definition Macho.h:1290
void execute(_StateInstance &instance) override
Definition Macho.h:1282
Definition Macho.h:1295
P3 myParam3
Definition Macho.h:1316
P4 myParam4
Definition Macho.h:1317
_Initializer5(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
Definition Macho.h:1297
P5 myParam5
Definition Macho.h:1318
void execute(_StateInstance &instance) override
Definition Macho.h:1309
P1 myParam1
Definition Macho.h:1314
P2 myParam2
Definition Macho.h:1315
_Initializer * clone() override
Definition Macho.h:1305
Definition Macho.h:1323
P1 myParam1
Definition Macho.h:1343
P2 myParam2
Definition Macho.h:1344
_Initializer * clone() override
Definition Macho.h:1334
P6 myParam6
Definition Macho.h:1348
P4 myParam4
Definition Macho.h:1346
_Initializer6(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
Definition Macho.h:1325
void execute(_StateInstance &instance) override
Definition Macho.h:1338
P3 myParam3
Definition Macho.h:1345
P5 myParam5
Definition Macho.h:1347
Definition Macho.h:1134
virtual ~_Initializer()=default
virtual Key adapt(Key key)
Definition Macho.h:1144
virtual _Initializer * clone()=0
virtual void execute(_StateInstance &instance)=0
virtual void destroy()
Definition Macho.h:1142
Definition Macho.h:1360
const _StateInstance * getInstance(ID id) const
Definition Macho.h:1402
_StateInstance * myPendingState
Definition Macho.h:1461
void allocate(unsigned int count)
void * myPendingBox
Definition Macho.h:1465
void setState(_StateInstance &instance, _Initializer *init)
friend class _StateInstance
Definition Macho.h:1452
class Alias currentState() const
_StateInstance *& getInstance(ID id)
Definition Macho.h:1397
void start(const Alias &state)
_Initializer * myPendingInit
Definition Macho.h:1462
void setPendingEvent(_IEventBase *event)
Definition Macho.h:1386
virtual ~_MachineBase()
void start(_StateInstance &instance)
void setState(const Alias &state)
_StateInstance * myCurrentState
Definition Macho.h:1458
void free(unsigned int count)
void setPendingState(_StateInstance &instance, _Initializer *init)
Definition Macho.h:1377
_IEventBase * myPendingEvent
Definition Macho.h:1467
_StateInstance ** myInstances
Definition Macho.h:1470
void clearHistoryDeep(unsigned int count, const _StateInstance &instance) const
Definition Macho.h:742
_RootInstance(_MachineBase &machine, _StateInstance *parent)
Definition Macho.h:746
const char * name() override
Definition Macho.h:768
void deleteBox() override
Definition Macho.h:763
ID id() override
Definition Macho.h:753
friend class _StateSpecification
Definition Macho.h:744
Key key() override
Definition Macho.h:757
void createBox() override
Definition Macho.h:762
_StateInstance * create(_MachineBase &machine, _StateInstance *parent) override
Definition Macho.h:771
Definition Macho.h:629
virtual _StateInstance * create(_MachineBase &machine, _StateInstance *parent)=0
void setBox(void *box)
Definition Macho.h:690
void exit(_StateInstance &next)
virtual void deleteBox()=0
void * myBoxPlace
Definition Macho.h:736
void setHistory(_StateInstance *history) const
Definition Macho.h:722
void shutdown()
Definition Macho.h:666
_MachineBase & machine()
Definition Macho.h:717
void entry(_StateInstance &previous, bool first=true)
void setHistorySuper(_StateInstance &deep)
Definition Macho.h:652
_StateInstance * myHistory
Definition Macho.h:733
bool isChild(const _StateInstance &instance)
Definition Macho.h:703
void init(bool history)
virtual const char * name()=0
_MachineBase & myMachine
Definition Macho.h:731
void * box()
Definition Macho.h:712
_StateInstance(_MachineBase &machine, _StateInstance *parent)
void restore(_StateInstance &instance)
Definition Macho.h:670
virtual Key key()=0
_StateSpecification & specification()
Definition Macho.h:707
void * myBox
Definition Macho.h:735
virtual void createBox()=0
void saveHistory(_StateInstance &shallow, _StateInstance &deep)
Definition Macho.h:646
_StateInstance * myParent
Definition Macho.h:734
_StateSpecification * mySpecification
Definition Macho.h:732
virtual ID id()=0
_StateInstance * history() const
Definition Macho.h:726
Definition Macho.h:386
static bool isChild(Key)
Definition Macho.h:390
friend class _StateInstance
Definition Macho.h:485
void setStateDirect(typename S::Box *box=0)
Definition Macho.h:1853
virtual void _setHistorySuper(_StateInstance &, _StateInstance &)
Definition Macho.h:458
void setStateBox(typename S::Box *box=0)
Definition Macho.h:1844
void setState(const class Alias &state)
void setState(_StateInstance &current)
void setStateHistory()
Definition Macho.h:1836
virtual void _restore(_StateInstance &current)
virtual ~_StateSpecification()=default
void setState()
Definition Macho.h:1786
_StateSpecification(_StateInstance &instance)
Definition Macho.h:395
Definition Macho.h:1152
Definition Macho.h:782
_StateInstance * create(_MachineBase &machine, _StateInstance *parent) override
Definition Macho.h:813
Key key() override
Definition Macho.h:808
const char * name() override
Definition Macho.h:802
typename S::Box Box
Definition Macho.h:795
ID id() override
Definition Macho.h:804
void deleteBox() override
Definition Macho.h:822
_SubstateInstance(_MachineBase &machine, _StateInstance *parent)
Definition Macho.h:787
void createBox() override
Definition Macho.h:817
~_SubstateInstance() override
Definition Macho.h:797
Definition Macho.h:1085
static void execute(Macho::_StateInstance &instance, const P1 &p1)
Definition Macho.h:1088
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
Definition Macho.h:1118
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
Definition Macho.h:1106
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2)
Definition Macho.h:1094
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
Definition Macho.h:1112
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3)
Definition Macho.h:1100
Definition Macho.h:289
void _deleteBox< _EmptyBox >(void *&box, void *&place)
void * _createBox< _EmptyBox >(void *&place)
static _HistoryInitializer _theHistoryInitializer
Definition Macho.h:1355
IEvent< TOP > * Event(R(TOP::*handler)(P1, P2, P3, P4, P5, P6), const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
Definition Macho.h:1042
void * _createBox(void *&place)
Definition Macho.h:320
void * Key
Definition Macho.h:302
Alias StateHistory(const _MachineBase &machine)
Definition Macho.h:1604
unsigned int ID
Definition Macho.h:306
static _DefaultInitializer _theDefaultInitializer
Definition Macho.h:1354
Alias State()
Definition Macho.h:1566
void _deleteBox(void *&box, void *&place)
Definition Macho.h:333
bool Check
Definition Macho.h:219
Definition Macho.h:214
Definition Macho.h:1653
TOP * operator->()
Definition Macho.h:1660
~AfterAdvice()
Definition Macho.h:1657
AfterAdvice(Machine< TOP > &m)
Definition Macho.h:1654
Definition Macho.h:366
const NameFn name
Definition Macho.h:377
const Generator instanceGenerator
Definition Macho.h:372
const char *(*)() NameFn
Definition Macho.h:369
bool(*)(Key) Predicate
Definition Macho.h:368
_StateInstance &(*)(_MachineBase &) Generator
Definition Macho.h:367
const ID id
Definition Macho.h:378
const Predicate childPredicate
Definition Macho.h:375