OpenRTM-aist 2.1.0
読み取り中…
検索中…
一致する文字列を見つけられません
Macho.h
[詳解]
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
208#if defined(__clang__)
209#if defined(_WIN32) || defined(_WIN64)
210#pragma clang diagnostic push
211#pragma clang diagnostic ignored "-Wreserved-identifier"
212#endif
213#endif
214
215
216class TestAccess;
217
218
220// Check type equality at compile time.
221template<class T, class U>
223};
224
225template<class T>
226struct CheckSameType<T, T> {
227 using Check = bool;
228};
229
230
232// Various macros for state and history declaration
233
234// Use this macro to define your top state class.
235#define TOPSTATE(TOP) \
236 struct TOP : public ::Macho::Link< TOP, ::Macho::TopBase< TOP > >
237
238// Use this macro for all other state classes.
239#define SUBSTATE(STATE, SUPERSTATE) \
240 struct STATE : public ::Macho::Link< STATE, SUPERSTATE >
241
242// Use this macro in your class definition to give it state functionality
243// (mandatory). If you have a state box declare it BEFORE macro invocation!
244#define STATE(S) \
245public: \
246 using SELF = S; \
247 /* Constructor and destructor already defined: you can't (and shouldn't) have your own! */ \
248 /* For the user a state class "constructor" and "destructor" are its entry and exit method! */ \
249 S(::Macho::_StateInstance & instance) : ::Macho::Link<S, SUPER>(instance) { \
250 /* Compile time check: S must derive directly from Link<S, SUPER> */ \
251 using MustDeriveFromLink = ::CheckSameType< ::Macho::Link<S, SUPER>, LINK>::Check; \
252 } \
253 ~S() {} \
254 static const char * _state_name() { return #S; } \
255 /* Get to your Box with this method: */ \
256 Box & box() { return *static_cast<Box *>(_box()); } \
257 friend class ::_VS8_Bug_101615;
258
259// Use this macro to select deep history strategy.
260#define DEEPHISTORY() \
261private: \
262 /* If no superstate has history, SUPER::_setHistorySuper is a NOOP */ \
263 void _saveHistory(::Macho::_StateInstance & self, ::Macho::_StateInstance & /* shallow */, ::Macho::_StateInstance & deep) override\
264 { self.setHistory(&deep); SELF::SUPER::_setHistorySuper(self, deep); } \
265protected: \
266 /* Substates may use _setHistorySuper to bubble up history */ \
267 void _setHistorySuper(::Macho::_StateInstance & self, ::Macho::_StateInstance & deep) override\
268 { self.setHistorySuper(deep); } \
269public:\
270 static_assert(true, "dummy for extra semicolon warning")
271
272// Use this macro to select shallow history strategy.
273#define HISTORY() \
274private: \
275 /* If no superstate has history, SUPER::_setHistorySuper is a NOOP */ \
276 virtual void _saveHistory(::Macho::_StateInstance & self, ::Macho::_StateInstance & shallow, ::Macho::_StateInstance & deep) \
277 { self.setHistory(&shallow); SELF::SUPER::_setHistorySuper(self, deep); } \
278protected: \
279 /* Substates may use _setHistorySuper to bubble up history */ \
280 virtual void _setHistorySuper(::Macho::_StateInstance & self, ::Macho::_StateInstance & deep) \
281 { self.setHistorySuper(deep); } \
282public:\
283 static_assert(true, "dummy for extra semicolon warning")
284
285// Use this macro to have boxes survive state transitions
286#define PERSISTENT() \
287private: \
288 virtual void _deleteBox(::Macho::_StateInstance & instance) {} \
289public:
290
291
293// Everything else is put into namespace 'Macho'.
294// Some identifiers are prefixed with an underscore to prevent name clashes with
295// deriving classes or to mark things as library internal. Don't touch things
296// with an underscore prefix!
297namespace Macho {
298
299 class _MachineBase;
300
301 template<class T>
302 class Machine;
303
304 template<class T>
305 class IEvent;
306
307 class _StateInstance;
308
309 // Unique identifier of states.
310 using Key = void*;
311
312 // Also an unique identifier of states, build from consecutive integers.
313 // Use Key to get to ID.
314 using ID = unsigned int;
315
316
318 // Box for states which don't declare own Box class.
319 class _EmptyBox {
320 public:
322 };
323
324
326 // Helper functions for box creation
327 template<class B>
328 void * _createBox(void * & place) {
329 if (!place)
330 place = ::operator new(sizeof(B));
331
332 new (place) B;
333
334 void * box = place;
335 place = nullptr;
336
337 return box;
338 }
339
340 template<class B>
341 void _deleteBox(void * & box, void * & place) {
342 assert(box);
343 assert(!place);
344
345 static_cast<B *>(box)->~B();
346 place = box;
347 box = nullptr;
348 }
349
350#ifdef MACHO_SNAPSHOTS
351 template<class B>
352 void * _cloneBox(void * other) {
353 assert(other);
354 return new B(*static_cast<B *>(other));
355 }
356#endif
357
358 // Specializations for EmptyBox:
359 // EmptyBox object gets reused over and over and never is deleted.
360 template<>
361 void * _createBox<_EmptyBox>(void * & place);
362
363 template<>
364 void _deleteBox<_EmptyBox>(void * & box, void * & place);
365
366#ifdef MACHO_SNAPSHOTS
367 template<>
368 void * _cloneBox<_EmptyBox>(void * other);
369#endif
370
371
373 // Essential information pointed at by state key.
374 struct _KeyData {
376 using Predicate = bool (*)(Key);
377 using NameFn = const char* (*)();
378
379 // Get StateInstance object from key.
381
382 // Is state of given key a child state?
384
386 const ID id;
387 };
388
389
391 // Base class for all state classes.
392 // Also serves as 'Root' state. By entering this state we trigger entry
393 // and exit actions of user's top state.
395 public:
396 virtual ~_StateSpecification() = default;
397
398 static bool isChild(Key /*key*/) {
399 return false;
400 }
401
402 protected:
404 : _myStateInstance(instance)
405 {}
406
407 // Initiate transition to a new state.
408 // Template parameter S is the new state to enter.
409 // Transition is performed AFTER control flow returns to the Machine object.
410 // Initiating more than one transition is considered an error!
411 // The new state may receive parameters for its 'init' methods:
412 // setState<StateA>("someData");
413 template<class S>
414 void setState();
415
416 template<class S, class P1>
417 void setState(const P1 & p1);
418
419 template<class S, class P1, class P2>
420 void setState(const P1 & p1, const P2 & p2);
421
422 template<class S, class P1, class P2, class P3>
423 void setState(const P1 & p1, const P2 & p2, const P3 & p3);
424
425 template<class S, class P1, class P2, class P3, class P4>
426 void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4);
427
428 template<class S, class P1, class P2, class P3, class P4, class P5>
429 void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5);
430
431 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
432 void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6);
433
434 // Initiate transition to a state's history.
435 // If state has no history, transition is to the state itself.
436 template<class S>
437 void setStateHistory();
438
439 // Initiate transition to a new state.
440 // Parameter 'state' is the new state to enter.
441 // See above and class 'Alias' for more information.
442 void setState(const class Alias & state);
443
444 // Deprectated!
445 template<class S>
446 void setStateBox(typename S::Box * box = 0);
447
448 // Deprectated!
449 template<class S>
450 void setStateDirect(typename S::Box * box = 0);
451
452 // 'Restore from snapshot' event: set current state.
453 // Default implementation: Does not trigger entry actions!
454 virtual void _restore(_StateInstance & current);
455
456 // only to be used in _restore
457 void setState(_StateInstance & current);
458
459 // 'Shutdown machine' event: exit all states.
460 // Default implementation: Triggers exit actions!
461 // Override empty to omit calling exit actions.
462 virtual void _shutdown();
463
464 // This is the method to bubble up history information
465 // for states whose superstates have no history (so does nothing).
466 virtual void _setHistorySuper(_StateInstance & /* self */, _StateInstance & /* deep*/ ) {}
467
468 private:
469 // State exit. Not allowed to initiate state change.
470 virtual void exit() {}
471
472 // State entry. Not allowed to initiate state change.
473 virtual void entry() {}
474
475 // Special kind of state entry: Upon transition to a new state,
476 // entry methods of that state and its superstates are called;
477 // 'init' however is called only on the one state the transition
478 // actually goes to.
479 // Is allowed to change state (to child states).
480 virtual void init() {}
481
482 private:
483 // C++ needs something like package visibility
484
485 // for _myStateInstance
486 template<class T>
487 friend class TopBase;
488
489 // for _getInstance
490 template<class C, class P>
491 friend class Link;
492
493 friend class _StateInstance;
494 friend class _RootInstance;
495
496 friend class _MachineBase;
497
498 // Create StateInstance object of state.
499 static _StateInstance & _getInstance(_MachineBase & machine);
500
501 virtual void _deleteBox(_StateInstance & /* instance */) {}
502
503 // Default history strategy (no history).
504 virtual void _saveHistory(_StateInstance & /* self */, _StateInstance & /* shallow */, _StateInstance & /* deep */) {}
505
506 private:
507 _StateInstance & _myStateInstance;
508 };
509
510
512 // Base class for user defined top state (and indirectly all other states).
513 template<class T>
515 public:
516 // This typedef is an alias for user defined top state in all (sub)states.
517 using TOP = T;
518
519 protected:
521 : _StateSpecification(instance)
522 {}
523
524 void dispatch(IEvent<TOP> * event);
525
526 const Machine<TOP> & machine();
527 };
528
529
531 // This class links substate specifications to superstate specifications by
532 // deriving from the superstate and being derived from by the substate.
533 // Substates inherit event handlers from superstates for reuse or redefinition
534 // this way.
535 template<class C, class P>
536 class Link : public P {
537 public:
538 // Alias for superstate.
539 using SUPER = P;
540
541 // Alias for topstate.
542 using TOP = typename P::TOP;
543
544 // Default box type.
545 using Box = _EmptyBox;
546
547 // Get unique key of state.
548 static Key key();
549
550 static Alias alias();
551
552 static bool isChild(Key other) {
553 return key() == other || SUPER::isChild(other);
554 }
555
556 static bool isParent(Key other) {
557 return static_cast<_KeyData *>(other)->childPredicate(key());
558 }
559
560 // Is machine m in this state?
561 static bool isCurrent(const _MachineBase & machine);
562
563 // Deprecated!
564 // Is machine m in exactly this state?
565 static bool isCurrentDirect(const _MachineBase & machine);
566
567 static void clearHistory(const _MachineBase & machine);
568
569 static void clearHistoryDeep(const _MachineBase & machine);
570
571 static Alias history(const _MachineBase & machine);
572
573 protected:
574 // Needed to perform compile time checks.
576
577 Link(_StateInstance & instance);
578
579 // These definitions seem redundant but they are not!
580 // They override parent definitions so each substate gets either
581 // this default or their own, but never its parents definitions.
582 void entry() override {}
583 void init() override {}
584 void exit() override {}
585
586 // This method keeps '_myStateInstance' attribute private.
587 void * _box();
588
589 private:
590 // for _getInstance
591 template<class U, class V>
592 friend class Link;
593
594 // for _getInstance
596
597 // for _getInstance
598 friend class Machine<TOP>;
599
600 // for _getInstance
601 friend class Alias;
602
603 // for Tests
604 friend class ::TestAccess;
605
606 // Create StateInstance object of state.
607 static _StateInstance & _getInstance(_MachineBase & machine);
608
609 // Box is by default not persistent. Not redundant!
610 void _deleteBox(_StateInstance & instance) override;
611
612 // Default history strategy (no history). Not redundant!
613 void _saveHistory(_StateInstance & self, _StateInstance & /*shallow*/, _StateInstance & deep) override {
614 // Bubble up history. If no superstate has history, _setHistorySuper will do nothing.
615 this->_setHistorySuper(self, deep);
616 }
617
618 private:
619 _StateInstance & _myStateInstance;
620 };
621
622
624 // Unique identifier for state S.
625 template<class S>
626 class StateID {
627 public:
628 static const ID value;
629 };
630
631
633 // StateInstance maintains machine specific data about a state. Keeps history, box
634 // and state object for state. StateInstance object is created the first time state
635 // is entered. There is at most one StateInstance object per state per machine
636 // instance.
638 protected:
640
641 public:
643
644 // Perform entry actions.
645 // 'first' is true on very first call.
646 void entry(_StateInstance & previous, bool first = true);
647
648 // Perform exit actions.
649 void exit(_StateInstance & next);
650
651 // Perform init action.
652 void init(bool history);
653
654 void saveHistory(_StateInstance & shallow, _StateInstance & deep) {
655 // Check state's history strategy.
656 mySpecification->_saveHistory(*this, shallow, deep);
657 }
658
659 // Update superstate's history information:
661 if (myParent != nullptr)
662 // Let it choose between deep or shallow history.
663 myParent->saveHistory(*this, deep);
664 }
665
666#ifdef MACHO_SNAPSHOTS
667 // Copy state of another StateInstance object.
668 void copy(_StateInstance & original);
669
670 // Create a clone of StateInstance object for another machine.
671 _StateInstance * clone(_MachineBase & newMachine);
672#endif
673
674 void shutdown() {
676 }
677
678 void restore(_StateInstance & instance) {
679 mySpecification->_restore(instance);
680 }
681
682 virtual ID id() = 0;
683
684 virtual Key key() = 0;
685
686 virtual const char * name() = 0;
687
688 // 'Virtual constructor' needed for cloning.
690
691 virtual void createBox() = 0;
692 virtual void deleteBox() = 0;
693#ifdef MACHO_SNAPSHOTS
694 virtual void cloneBox(void * box) = 0;
695#endif
696
697 // Deprecated!
698 void setBox(void * box) {
699 assert(!myBox);
700
701 if (myBoxPlace != nullptr) {
702 // Free cached memory of previously used box.
703 ::operator delete(myBoxPlace);
704 myBoxPlace = nullptr;
705 }
706
707 myBox = box;
708 }
709
710 // Is 'instance' a superstate?
711 bool isChild(const _StateInstance & instance) {
712 return this == &instance || ((myParent != nullptr) && myParent->isChild(instance));
713 }
714
719
720 void * box() {
721 assert(myBox);
722 return myBox;
723 }
724
726 return myMachine;
727 }
728
729 // const: History can be manipulated even on a const object.
732 }
733
735 return myHistory;
736 }
737
738 protected:
740 _StateSpecification * mySpecification; // Instance of state class
743 void * myBox;
744 void * myBoxPlace; // Reused box heap memory
745 };
746
747
749 // StateInstance for Root state (the real top state).
751 protected:
753
759
760 public:
761 ID id() override {
762 return 0;
763 }
764
765 Key key() override {
766 // Can't happen: key is only called by users, and they don't know about Root.
767 assert(false); return nullptr;
768 }
769
770 void createBox() override {}
771 void deleteBox() override {}
772#ifdef MACHO_SNAPSHOTS
773 virtual void cloneBox(void * box) {}
774#endif
775
776 const char * name() override { return "Root"; }
777
778 // 'Virtual constructor' needed for cloning.
780 return new _RootInstance(machine, parent);
781 }
782
783 };
784
785
787 // StateInstance for substates (including Top ;-)
788 // Has methods to create state specific objects.
789 template<class S>
791 protected:
792 template<class C, class P>
793 friend class Link;
794
796 : _StateInstance(machine, parent)
797 {
798 assert(parent);
799 this->mySpecification = new S(*this);
800 }
801
802 public:
803 using Box = typename S::Box;
804
806 if (this->myBox)
807 Macho::_deleteBox<Box>(myBox, myBoxPlace);
808 }
809
810 const char * name() override { return S::_state_name(); }
811
812 ID id() override {
813 return StateID<S>::value;
814 }
815
816 Key key() override {
817 return S::key();
818 }
819
820 // 'Virtual constructor' needed for cloning.
822 return new _SubstateInstance<S>(machine, parent);
823 }
824
825 void createBox() override {
826 if (!this->myBox)
827 this->myBox = Macho::_createBox<Box>(myBoxPlace);
828 }
829
830 void deleteBox() override {
831 assert(myBox);
832 Macho::_deleteBox<Box>(myBox, myBoxPlace);
833 }
834
835#ifdef MACHO_SNAPSHOTS
836 virtual void cloneBox(void * box) {
837 assert(!myBox);
838 assert(!myBoxPlace);
839 // Needs copy constructor in ALL box types.
840 myBox = Macho::_cloneBox<Box>(box);
841 }
842#endif
843
844 };
845
846
848 // Definitions for queuable event types
849
850 // Generic interface for event objects (available only to MachineBase)
852 public:
853 virtual ~_IEventBase() = default;
854 virtual void dispatch(_StateInstance &) = 0;
855 };
856
857
858 // Interface for event objects (bound to a top state)
859 template<class TOP>
860 class IEvent : protected _IEventBase {
861 friend class Machine<TOP>;
862 friend class TopBase<TOP>;
863 };
864
865
866 // Event with four parameters
867 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5, class P6>
868 class _Event6 : public IEvent<TOP> {
869 using Signature = R (TOP::*)(P1, P2, P3, P4, P5, P6);
870
871 public:
872 _Event6(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6)
873 : myHandler(handler)
874 , myParam1(p1)
875 , myParam2(p2)
876 , myParam3(p3)
877 , myParam4(p4)
878 , myParam5(p5)
879 , myParam6(p6)
880 {}
881
882 protected:
883 void dispatch(_StateInstance & instance) {
884 TOP & behaviour = static_cast<TOP &>(instance.specification());
886 }
887
888 Signature myHandler;
895 };
896
897
898 // Event with four parameters
899 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5>
900 class _Event5 : public IEvent<TOP> {
901 using Signature = R (TOP::*)(P1, P2, P3, P4, P5);
902
903 public:
904 _Event5(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5)
905 : myHandler(handler)
906 , myParam1(p1)
907 , myParam2(p2)
908 , myParam3(p3)
909 , myParam4(p4)
910 , myParam5(p5)
911 {}
912
913 protected:
914 void dispatch(_StateInstance & instance) {
915 TOP & behaviour = static_cast<TOP &>(instance.specification());
917 }
918
919 Signature myHandler;
925 };
926
927
928 // Event with four parameters
929 template<class TOP, class R, class P1, class P2, class P3, class P4>
930 class _Event4 : public IEvent<TOP> {
931 using Signature = R (TOP::*)(P1, P2, P3, P4);
932
933 public:
934 _Event4(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4)
935 : myHandler(handler)
936 , myParam1(p1)
937 , myParam2(p2)
938 , myParam3(p3)
939 , myParam4(p4)
940 {}
941
942 protected:
943 void dispatch(_StateInstance & instance) {
944 TOP & behaviour = static_cast<TOP &>(instance.specification());
946 }
947
948 Signature myHandler;
953 };
954
955
956 // Event with three parameters
957 template<class TOP, class R, class P1, class P2, class P3>
958 class _Event3 : public IEvent<TOP> {
959 using Signature = R (TOP::*)(P1, P2, P3);
960
961 public:
962 _Event3(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3)
963 : myHandler(handler)
964 , myParam1(p1)
965 , myParam2(p2)
966 , myParam3(p3)
967 {}
968
969 protected:
970 void dispatch(_StateInstance & instance) {
971 TOP & behaviour = static_cast<TOP &>(instance.specification());
972 (behaviour.*myHandler)(myParam1, myParam2, myParam3);
973 }
974
975 Signature myHandler;
979 };
980
981
982 // Event with two parameters
983 template<class TOP, class R, class P1, class P2>
984 class _Event2 : public IEvent<TOP> {
985 using Signature = R (TOP::*)(P1, P2);
986
987 public:
988 _Event2(Signature handler, const P1 & p1, const P2 & p2)
989 : myHandler(handler)
990 , myParam1(p1)
991 , myParam2(p2)
992 {}
993
994 protected:
995 void dispatch(_StateInstance & instance) {
996 TOP & behaviour = static_cast<TOP &>(instance.specification());
997 (behaviour.*myHandler)(myParam1, myParam2);
998 }
999
1000 Signature myHandler;
1003 };
1004
1005
1006 // Event with one parameter
1007 template<class TOP, class R, class P1>
1008 class _Event1 : public IEvent<TOP> {
1009 using Signature = R (TOP::*)(P1);
1010
1011 public:
1012 _Event1(Signature handler, const P1 & p1)
1013 : myHandler(handler)
1014 , myParam1(p1)
1015 {}
1016
1017 protected:
1018 void dispatch(_StateInstance & instance) override {
1019 TOP & behaviour = static_cast<TOP &>(instance.specification());
1020 (behaviour.*myHandler)(myParam1);
1021 }
1022
1023 Signature myHandler;
1025 };
1026
1027
1028 // Event with no parameters
1029 template<class TOP, class R>
1030 class _Event0 : public IEvent<TOP> {
1031 using Signature = R (TOP::*)();
1032
1033 public:
1034 _Event0(Signature handler)
1035 : myHandler(handler)
1036 {}
1037
1038 protected:
1039 void dispatch(_StateInstance & instance) override {
1040 TOP & behaviour = static_cast<TOP &>(instance.specification());
1041 (behaviour.*myHandler)();
1042 }
1043
1044 Signature myHandler;
1045 };
1046
1047
1048 // Event creating functions using type inference
1049 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5, class P6>
1050 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) {
1051 return new _Event6<TOP, R, P1, P2, P3, P4, P5, P6>(handler, p1, p2, p3, p4, p5, p6);
1052 }
1053
1054 // Event creating functions using type inference
1055 template<class TOP, class R, class P1, class P2, class P3, class P4, class P5>
1056 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) {
1057 return new _Event5<TOP, R, P1, P2, P3, P4, P5>(handler, p1, p2, p3, p4, p5);
1058 }
1059
1060 // Event creating functions using type inference
1061 template<class TOP, class R, class P1, class P2, class P3, class P4>
1062 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1063 return new _Event4<TOP, R, P1, P2, P3, P4>(handler, p1, p2, p3, p4);
1064 }
1065
1066 template<class TOP, class R, class P1, class P2, class P3>
1067 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3), const P1 & p1, const P2 & p2, const P3 & p3) {
1068 return new _Event3<TOP, R, P1, P2, P3>(handler, p1, p2, p3);
1069 }
1070
1071 template<class TOP, class R, class P1, class P2>
1072 inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2), const P1 & p1, const P2 & p2) {
1073 return new _Event2<TOP, R, P1, P2>(handler, p1, p2);
1074 }
1075
1076 template<class TOP, class R, class P1>
1077 inline IEvent<TOP> * Event(R (TOP::*handler)(P1), const P1 & p1) {
1078 return new _Event1<TOP, R, P1>(handler, p1);
1079 }
1080
1081 template<class TOP, class R>
1082 inline IEvent<TOP> * Event(R (TOP::*handler)()) {
1083 return new _Event0<TOP, R>(handler);
1084 }
1085
1086} // namespace Macho
1087
1088
1090// MSVC++ 8.0 does not handle qualified member template friends
1091// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101615
1092// Otherwise call could happen directly in Initializer classes.
1094public:
1095 template<class S, class P1>
1096 static inline void execute(Macho::_StateInstance & instance, const P1 & p1) {
1097 S & behaviour = static_cast<S &>(instance.specification());
1098 behaviour.init(p1);
1099 }
1100
1101 template<class S, class P1, class P2>
1102 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2) {
1103 S & behaviour = static_cast<S &>(instance.specification());
1104 behaviour.init(p1, p2);
1105 }
1106
1107 template<class S, class P1, class P2, class P3>
1108 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3) {
1109 S & behaviour = static_cast<S &>(instance.specification());
1110 behaviour.init(p1, p2, p3);
1111 }
1112
1113 template<class S, class P1, class P2, class P3, class P4>
1114 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1115 S & behaviour = static_cast<S &>(instance.specification());
1116 behaviour.init(p1, p2, p3, p4);
1117 }
1118
1119 template<class S, class P1, class P2, class P3, class P4, class P5>
1120 static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1121 S & behaviour = static_cast<S &>(instance.specification());
1122 behaviour.init(p1, p2, p3, p4, p5);
1123 }
1124
1125 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1126 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) {
1127 S & behaviour = static_cast<S &>(instance.specification());
1128 behaviour.init(p1, p2, p3, p4, p5, p6);
1129 }
1130
1131};
1132
1133
1135namespace Macho {
1136
1138 // Base class for state initializers.
1139 // Initializer are used to provide parameters to states.
1140 // The 'execute' method of Initializers will call a state's init method with
1141 // the data of the initializer object.
1143 public:
1144 virtual ~_Initializer() = default;
1145
1146 // Create copy of initializer.
1147 virtual _Initializer * clone() = 0;
1148
1149 // Deallocate object.
1150 virtual void destroy() { delete this; }
1151
1152 virtual Key adapt(Key key) { return key; }
1153
1154 // Initialize given state. State is new current state of a state machine.
1155 virtual void execute(_StateInstance & instance) = 0;
1156 };
1157
1158
1159 // Base class for Singleton initializers.
1161 // Copy of Singleton is Singleton.
1162 _Initializer * clone() override { return this; }
1163
1164 // Singletons are never destroyed.
1165 void destroy() override {}
1166 };
1167
1168
1169 // Default initializer: provides no parameters, calls state's 'init' method
1170 // only.
1172 public:
1173 void execute(_StateInstance & instance) override {
1174 instance.init(false);
1175 }
1176 };
1177
1178
1179 // History initializer: provides no parameters, performs transition to
1180 // history of state if available.
1182 public:
1183 void execute(_StateInstance & instance) override {
1184 instance.init(true);
1185 }
1186 };
1187
1188
1189 // Special initializer: Helps alias impersonate as history state of given state.
1191 public:
1192 _AdaptingInitializer(const _MachineBase & machine) : myMachine(machine) {}
1193
1194 void execute(_StateInstance & instance) override {
1195 instance.init(true);
1196 }
1197
1198 _Initializer * clone() override {
1199 return new _AdaptingInitializer(myMachine);
1200 }
1201
1202 Key adapt(Key key) override;
1203
1204 protected:
1206 };
1207
1208
1209 // Initializers with one to six parameters.
1210 template<class S, class P1>
1212 public:
1213 _Initializer1(const P1 & p1)
1214 : myParam1(p1)
1215 {}
1216
1217 _Initializer * clone() override {
1218 return new _Initializer1<S, P1>(myParam1);
1219 }
1220
1221 void execute(_StateInstance & instance) override {
1222 ::_VS8_Bug_101615::execute<S, P1>(instance, myParam1);
1223 delete this;
1224 }
1225
1227 };
1228
1229
1230 template<class S, class P1, class P2>
1232 public:
1233 _Initializer2(const P1 & p1, const P2 & p2)
1234 : myParam1(p1)
1235 , myParam2(p2)
1236 {}
1237
1238 _Initializer * clone() override {
1240 }
1241
1242 void execute(_StateInstance & instance) override {
1243 ::_VS8_Bug_101615::execute<S, P1, P2>(instance, myParam1, myParam2);
1244 delete this;
1245 }
1246
1249 };
1250
1251
1252 template<class S, class P1, class P2, class P3>
1254 public:
1255 _Initializer3(const P1 & p1, const P2 & p2, const P3 & p3)
1256 : myParam1(p1)
1257 , myParam2(p2)
1258 , myParam3(p3)
1259 {}
1260
1264
1265 void execute(_StateInstance & instance) override {
1266 ::_VS8_Bug_101615::execute<S, P1, P2, P3>(instance, myParam1, myParam2, myParam3);
1267 delete this;
1268 }
1269
1273 };
1274
1275
1276 template<class S, class P1, class P2, class P3, class P4>
1278 public:
1279 _Initializer4(const P1 & p1, const P2 & p2, const P3 & p3, P4 & p4)
1280 : myParam1(p1)
1281 , myParam2(p2)
1282 , myParam3(p3)
1283 , myParam4(p4)
1284 {}
1285
1289
1290 void execute(_StateInstance & instance) override {
1291 ::_VS8_Bug_101615::execute<S, P1, P2, P3, P4>(instance, myParam1, myParam2, myParam3, myParam4);
1292 delete this;
1293 }
1294
1299 };
1300
1301
1302 template<class S, class P1, class P2, class P3, class P4, class P5>
1304 public:
1305 _Initializer5(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5)
1306 : myParam1(p1)
1307 , myParam2(p2)
1308 , myParam3(p3)
1309 , myParam4(p4)
1310 , myParam5(p5)
1311 {}
1312
1316
1317 void execute(_StateInstance & instance) override {
1318 ::_VS8_Bug_101615::execute<S, P1, P2, P3, P4, P5>(instance, myParam1, myParam2, myParam3, myParam4, myParam5);
1319 delete this;
1320 }
1321
1327 };
1328
1329
1330 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1332 public:
1333 _Initializer6(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6)
1334 : myParam1(p1)
1335 , myParam2(p2)
1336 , myParam3(p3)
1337 , myParam4(p4)
1338 , myParam5(p5)
1339 , myParam6(p6)
1340 {}
1341
1345
1346 void execute(_StateInstance & instance) override {
1347 _VS8_Bug_101615::execute<S, P1, P2, P3, P4, P5, P6>(instance, myParam1, myParam2, myParam3, myParam4, myParam5, myParam6);
1348 delete this;
1349 }
1350
1357 };
1358
1359
1361 // Singleton initializers.
1364
1365
1367 // Base class for Machine objects.
1369 public:
1370 class Alias currentState() const;
1371
1372 protected:
1374 virtual ~_MachineBase();
1375
1376 // Transition to new state.
1377 void setState(_StateInstance & instance, _Initializer * init);
1378
1379 // Transition to new state specified by state alias.
1380 void setState(const Alias & state);
1381
1382 // Prepare transition to new state (performed on call to 'rattleOn').
1383 // There can be only one state transition pending (asserts otherwise)!
1384 // 'init' is an initializer for the new state.
1386 assert( (!myPendingState || myPendingState == &instance) &&
1387 "There is already a state transition pending!");
1388
1389 myPendingState = &instance;
1390 myPendingInit = init;
1391 }
1392
1393 // Provide event object to be executed on current state.
1395 assert(event);
1396 assert(!myPendingEvent && "There is already an event pending!");
1397
1398 myPendingEvent = event;
1399 }
1400
1401 // Performs pending state transition.
1402 void rattleOn();
1403
1404 // Get StateInstance object for ID.
1406 return myInstances[id];
1407 }
1408
1409 // Get StateInstance object for ID.
1410 const _StateInstance * getInstance(ID id) const {
1411 return myInstances[id];
1412 }
1413
1414 // Starts the machine with the specified start state.
1415 void start(_StateInstance & instance);
1416 void start(const Alias & state);
1417
1418 // Shuts machine down. Will exit any states and free all allocated
1419 // resources.
1420 void shutdown();
1421
1422 // Allocate space for pointers to StateInstance objects.
1423 void allocate(unsigned int count);
1424
1425 // Free all StateInstance objects.
1426 void free(unsigned int count);
1427
1428 // const: History can be manipulated even on a const machine.
1429 void clearHistoryDeep(unsigned int count, const _StateInstance & instance) const;
1430
1431#ifdef MACHO_SNAPSHOTS
1432 // Create a copy of another machines StateInstance objects (includes boxes).
1433 void copy(_StateInstance ** other, unsigned int count);
1434
1435 // Create a copy of another machines StateInstance object.
1436 _StateInstance * createClone(ID id, _StateInstance * original);
1437#endif
1438
1439 protected:
1440 // C++ needs something like package visibility
1441
1442 // for getInstance
1443 template<class C, class P>
1444 friend class Link;
1445
1446 // for setPendingEvent
1447 template<class T>
1448 friend class TopBase;
1449
1450 // for getInstance
1452
1453 // for getInstance
1454 friend class Alias;
1455
1456 // for getInstance
1458
1459 // for setPendingState
1460 friend class _StateInstance;
1461
1462 // for Tests
1463 friend class ::TestAccess;
1464
1465 // Current state of Machine object.
1467
1468 // Information about pending state transition.
1471
1472 // Deprecated!
1473 void * myPendingBox{nullptr};
1474
1476
1477 // Array of StateInstance objects.
1479 };
1480
1481
1483 // This is the base class for state aliases. A state alias represents a
1484 // state of a machine. A transition to that state can be initiated by
1485 // giving the alias object to the 'setState' method.
1486 //
1487 // State aliases are created by the template functions 'State' further below.
1488 // Parameters can be provided to these functions that will be used to
1489 // initialize the state on transition to it.
1490 class Alias {
1491 public:
1492 Alias(Key key, bool history = false)
1493 : myStateKey(key)
1494 , myInitializer(
1495 history ?
1496 static_cast<_Initializer *>(&_theHistoryInitializer)
1497 :
1498 static_cast<_Initializer *>(&_theDefaultInitializer)
1499 )
1500 {
1501 assert(key);
1502 }
1503
1505 : myStateKey(key)
1506 , myInitializer(init)
1507 {
1508 assert(key);
1509 }
1510
1511 Alias(const Alias & other)
1512 : myStateKey(other.myStateKey)
1513 , myInitializer(other.myInitializer->clone())
1514 {}
1515
1516 Alias & operator=(const Alias & other) {
1517 if (this == &other) return *this;
1518
1520
1521 myStateKey = other.myStateKey;
1523
1524 return *this;
1525 }
1526
1529 }
1530
1531 // Use this to test validity: zero means invalid alias.
1532 operator Key() const {
1533 return key();
1534 }
1535
1536 bool isChild(Key k) const {
1537 return key()->childPredicate(k);
1538 }
1539
1540 bool isParent(Key k) const {
1541 return static_cast<_KeyData *>(k)->childPredicate(key());
1542 }
1543
1544 const char * name() const {
1545 return key()->name();
1546 }
1547
1548 ID id() const {
1549 return key()->id;
1550 }
1551
1552 protected:
1553 friend class _MachineBase;
1555
1556 void setState(_MachineBase & machine) const;
1557
1558 _KeyData * key() const { return static_cast<_KeyData *>(myInitializer->adapt(myStateKey)); }
1559
1560 protected:
1561 // Key of specified state.
1563
1564 // Initializer of this alias.
1566 };
1567
1568 // Deprecated!
1570
1571
1572 // Create alias with 0 to 6 parameters.
1573 template<class S>
1575 return Alias(S::key());
1576 }
1577
1578 template<class S, class P1>
1579 Alias State(const P1 & p1) {
1580 return Alias(S::key(), new _Initializer1<S, P1>(p1));
1581 }
1582
1583 template<class S, class P1, class P2>
1584 Alias State(const P1 & p1, const P2 & p2) {
1585 return Alias(S::key(), new _Initializer2<S, P1, P2>(p1, p2));
1586 }
1587
1588 template<class S, class P1, class P2, class P3>
1589 Alias State(const P1 & p1, const P2 & p2, const P3 & p3) {
1590 return Alias(S::key(), new _Initializer3<S, P1, P2, P3>(p1, p2, p3));
1591 }
1592
1593 template<class S, class P1, class P2, class P3, class P4>
1594 Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1595 return Alias(S::key(), new _Initializer4<S, P1, P2, P3, P4>(p1, p2, p3, p4));
1596 }
1597
1598 template<class S, class P1, class P2, class P3, class P4, class P5>
1599 Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1600 return Alias(S::key(), new _Initializer5<S, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5));
1601 }
1602
1603 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1604 Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
1605 return Alias(S::key(), new _Initializer6<S, P1, P2, P3, P4, P5, P6>(p1, p2, p3, p4, p5, p6));
1606 }
1607
1608 // Create alias for state's history: not the current history state, but
1609 // really the history of a state. This means that the alias may point to
1610 // different states during its life. Needs a machine instance to take history from.
1611 template<class S>
1613 return Alias(S::key(), new _AdaptingInitializer(machine));
1614 }
1615
1616
1618 // Snapshot of a machine object.
1619 // Saves the state of a machine object at a specific point in time to be restored
1620 // later (can be used to achieve something like backtracking).
1621 // Includes boxes of current state and persistent boxes.
1622 // Assign a snapshot to a machine (operator=) to restore state.
1623 // Note that no exit/entry actions of the overwritten machine state are performed!
1624 // Box destructors however are executed!
1625#ifdef MACHO_SNAPSHOTS
1626 template<class TOP>
1627 class Snapshot : public _MachineBase {
1628 public:
1629 Snapshot(Machine<TOP> & machine);
1630
1631 ~Snapshot() {
1632 free(Machine<TOP>::theStateCount);
1633 }
1634
1635 private:
1636 friend class Machine<TOP>;
1637
1638 Snapshot(const Snapshot<TOP> & other);
1639 Snapshot & operator=(const Snapshot<TOP> & other);
1640 };
1641#endif
1642
1643
1645 // A Machine object maintains a current state.
1646 // The state can be any substate of template parameter TOP.
1647 // TOP is the Machine's top most and inital state. TOP must be defined by
1648 // the macro TOPSTATE. Event processing is done by calling methods (event
1649 // handlers) on the current state.
1650 // This is realized by defining an arrow ('->') operator on Machine,
1651 // forwarding to the interface of TOP.
1652 // Every possible event handler to be called must therefore appear in the
1653 // interface of TOP. Events are dispatched by using this operator on a
1654 // Machine object (e.g. 'machine->event()').
1655 template<class TOP>
1656 class Machine : public _MachineBase {
1657 public:
1658
1659 // This class performs an action in its destructor after an event
1660 // handler has finished. Comparable to an After Advice in AOP.
1662 AfterAdvice(Machine<TOP> & m) : myMachine(m) {}
1663
1664 // Event handler has finished execution. Execute pending transitions now.
1665 ~AfterAdvice() { myMachine.rattleOn(); }
1666
1667 // this arrow operator finally dispatches to TOP interface.
1668 TOP * operator->() {
1669 return static_cast<TOP *>(& (myMachine.myCurrentState->specification()) );
1670 }
1671
1672 private:
1673 Machine<TOP> & myMachine;
1674 };
1675
1677 // Compile time check: TOP must directly derive from TopBase<TOP>
1678 using MustDeriveFromTopBase = typename CheckSameType<TopBase<TOP>, typename TOP::SUPER>::Check;
1679 // suppress unused-typdefs warnig
1680 static_assert(static_cast<MustDeriveFromTopBase*>(nullptr)==nullptr, "dummy");
1681
1682 allocate(theStateCount);
1683 start(TOP::_getInstance(*this));
1684 }
1685
1686 // Initialize with a state alias object to have machine go to a state
1687 // other than TOP on startup.
1688 Machine(const Alias & state) {
1689 // Compile time check: TOP must directly derive from TopBase<TOP>
1690 using MustDeriveFromTopBase = typename CheckSameType<TopBase<TOP>, typename TOP::SUPER>::Check;
1691 // suppress unused-typdefs warnig
1692 static_assert(static_cast<MustDeriveFromTopBase*>(nullptr)==nullptr, "dummy");
1693
1694 allocate(theStateCount);
1695 start(state);
1696 }
1697
1698#ifdef MACHO_SNAPSHOTS
1699 // Create machine from a snapshot.
1700 Machine(const Snapshot<TOP> & snapshot) {
1701 allocate(theStateCount);
1702 copy(snapshot.myInstances, theStateCount);
1703 }
1704
1705 // Overwrite current machine state by snapshot.
1706 Machine<TOP> & operator=(const Snapshot<TOP> & snapshot) {
1707 assert(!myPendingState);
1708 assert(!myPendingEvent);
1709
1711
1712 free(theStateCount);
1713 copy(snapshot.myInstances, theStateCount);
1714
1715 // Go to Root state first
1717
1718 // Then set previous current state
1719 _StateInstance * current = getInstance(snapshot.myCurrentState->id());
1720 current->restore(*current);
1721 rattleOn();
1722
1723 return *this;
1724 }
1725#endif
1726
1727 ~Machine() override {
1729 free(theStateCount);
1730 }
1731
1732 // Don't return pointer to interface right now: we need to know when the
1733 // event handler has finished; return an AfterAdvice object instead:
1734 // it allows us to perform actions after access.
1736 assert(myCurrentState);
1737 assert(!myPendingState);
1738
1739 // We need to know when the event handler has finished.
1740 return AfterAdvice(*this);
1741 }
1742
1743 // Dispatch an event object to machine.
1744 void dispatch(IEvent<TOP> * event, bool destroy = true) {
1745 assert(event);
1746
1747 event->dispatch(*myCurrentState);
1748 if (destroy) delete event;
1749
1750 rattleOn();
1751 }
1752
1753 // Allow (const) access to top state's box (for state data extraction).
1754 const typename TOP::Box & box() const {
1755 assert(myCurrentState);
1756 return static_cast<TOP &>(myCurrentState->specification()).TOP::box();
1757 }
1758
1759 private:
1760 template<class C, class P>
1761 friend class Link;
1762
1763 private:
1764 Machine(const Machine<TOP> & other) = delete;
1765 Machine<TOP> & operator=(const Machine<TOP> & other) = delete;
1766
1767#ifdef MACHO_SNAPSHOTS
1768 friend class Snapshot<TOP>;
1769#endif
1770
1771 template<class T> friend class StateID;
1772
1773 // Next free identifier for StateInstance objects.
1774 static ID theStateCount;
1775 };
1776
1777 // Root is always there and has ID 0, so start from 1
1778 template<class TOP>
1780
1781 // Each state has a unique ID number.
1782 // The identifiers are consecutive integers starting from zero,
1783 // which allows use as index into a vector for fast access.
1784 // 'Root' always has zero as id.
1785 //template<class S>
1786 //const ID StateID<S>::value = Machine<typename S::TOP>::theStateCount++;
1787
1788
1790 // Implementation for StateSpecification
1791
1792 // Initiate state transition with 0 to six parameters.
1793 template<class S>
1795 _MachineBase & m = _myStateInstance.machine();
1796 _StateInstance & instance = S::_getInstance(m);
1798 }
1799
1800 template<class S, class P1>
1801 inline void _StateSpecification::setState(const P1 & p1) {
1802 _MachineBase & m = _myStateInstance.machine();
1803 _StateInstance & instance = S::_getInstance(m);
1804 m.setPendingState(instance, new _Initializer1<S, P1>(p1));
1805 }
1806
1807 template<class S, class P1, class P2>
1808 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2) {
1809 _MachineBase & m = _myStateInstance.machine();
1810 _StateInstance & instance = S::_getInstance(m);
1811 m.setPendingState(instance, new _Initializer2<S, P1, P2>(p1, p2));
1812 }
1813
1814 template<class S, class P1, class P2, class P3>
1815 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3) {
1816 _MachineBase & m = _myStateInstance.machine();
1817 _StateInstance & instance = S::_getInstance(m);
1818 m.setPendingState(instance, new _Initializer3<S, P1, P2, P3>(p1, p2, p3));
1819 }
1820
1821 template<class S, class P1, class P2, class P3, class P4>
1822 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
1823 _MachineBase & m = _myStateInstance.machine();
1824 _StateInstance & instance = S::_getInstance(m);
1825 m.setPendingState(instance, new _Initializer4<S, P1, P2, P3, P4>(p1, p2, p3, p4));
1826 }
1827
1828 template<class S, class P1, class P2, class P3, class P4, class P5>
1829 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
1830 _MachineBase & m = _myStateInstance.machine();
1831 _StateInstance & instance = S::_getInstance(m);
1832 m.setPendingState(instance, new _Initializer5<S, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5));
1833 }
1834
1835 template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
1836 inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
1837 _MachineBase & m = _myStateInstance.machine();
1838 _StateInstance & instance = S::_getInstance(m);
1839 m.setPendingState(instance, new _Initializer6<S, P1, P2, P3, P4, P5, P6>(p1, p2, p3, p4, p5, p6));
1840 }
1841
1842 // Initiate state transition to a state's history.
1843 template<class S>
1845 _MachineBase & m = _myStateInstance.machine();
1846 _StateInstance & instance = S::_getInstance(m);
1848 }
1849
1850 // Deprecated!
1851 template<class S>
1852 inline void _StateSpecification::setStateBox(typename S::Box * box) {
1853 _MachineBase & m = _myStateInstance.machine();
1854 _StateInstance & instance = S::_getInstance(m);
1855 m.myPendingBox = box;
1857 }
1858
1859 // Deprecated!
1860 template<class S>
1861 inline void _StateSpecification::setStateDirect(typename S::Box * box) {
1862 _MachineBase & m = _myStateInstance.machine();
1863 _StateInstance & instance = S::_getInstance(m);
1864 m.myPendingBox = box;
1866 }
1867
1868
1870 // Implementation for TopBase
1871 template<class T>
1872 inline void TopBase<T>::dispatch(IEvent<TOP> * event) {
1873 assert(event);
1874 _myStateInstance.machine().setPendingEvent(event);
1875 }
1876
1877 template<class T>
1878 // Returns current state machine instance.
1880 return static_cast<Machine<TOP> &>(this->_myStateInstance.machine());
1881 }
1882
1883
1885 // Implementation for Link
1886 template<class C, class P>
1888 : P(P::_getInstance(instance.machine()))
1889 // Can't initialize _myStateInstance with _getInstance,
1890 // because this would result in an endless loop (at least for first call)
1891 , _myStateInstance(instance)
1892 {}
1893
1894 // This method keeps '_myStateInstance' attribute private.
1895 template<class C, class P>
1896 inline void * Link<C, P>::_box() {
1897 return _myStateInstance.box();
1898 }
1899
1900 // Default behaviour: free box on exit.
1901 template<class C, class P>
1902 inline void Link<C, P>::_deleteBox(_StateInstance & instance) {
1903 instance.deleteBox();
1904 }
1905
1906 // Create StateInstance object of state.
1907 template<class C, class P>
1908 /* static */ inline _StateInstance & Link<C, P>::_getInstance(_MachineBase & machine) {
1909 // Look first in machine for existing StateInstance.
1910 _StateInstance * & instance = machine.getInstance(StateID<C>::value);
1911 if (instance == nullptr)
1912 // Will create parent StateInstance object if not already created.
1913 instance = new _SubstateInstance<C>(machine, &P::_getInstance(machine));
1914
1915 return *instance;
1916 }
1917
1918 template<class C, class P>
1919 /* static */ inline bool Link<C, P>::isCurrent(const _MachineBase & machine) {
1920 return machine.currentState().isChild(key());
1921 }
1922
1923 // Deprecated!
1924 template<class C, class P>
1925 /* static */ inline bool Link<C, P>::isCurrentDirect(const _MachineBase & machine) {
1926 return key() == machine.currentState();
1927 }
1928
1929 template<class C, class P>
1930 /* static */ void Link<C, P>::clearHistory(const _MachineBase & machine) {
1931 const _StateInstance * instance = machine.getInstance(StateID<C>::value);
1932 if (instance != nullptr)
1933 instance->setHistory(nullptr);
1934 }
1935
1936 template<class C, class P>
1937 /* static */ void Link<C, P>::clearHistoryDeep(const _MachineBase & machine) {
1938 const _StateInstance * instance = machine.getInstance(StateID<C>::value);
1939 if (instance != nullptr)
1941 }
1942
1943 template<class C, class P>
1944 /* static */ Alias Link<C, P>::history(const _MachineBase & machine) {
1945 const _StateInstance * instance = machine.getInstance(StateID<C>::value);
1946 _StateInstance * history = nullptr;
1947
1948 if (instance != nullptr)
1949 history = instance->history();
1950
1951 return history != nullptr ? history->key() : key();
1952 }
1953
1954 template<class C, class P>
1955 /* static */ inline Key Link<C, P>::key() {
1956 static _KeyData k = { _getInstance, isChild, C::_state_name, StateID<C>::value };
1957 return &k;
1958 }
1959
1960 template<class C, class P>
1961 /* static */ inline Alias Link<C, P>::alias() {
1962 return Alias(key());
1963 }
1964
1965
1967 // Implementation for Snapshot
1968#ifdef MACHO_SNAPSHOTS
1969 template<class TOP>
1970 Snapshot<TOP>::Snapshot(Machine<TOP> & machine) {
1971 assert(!machine.myPendingState);
1972 assert(!machine.myPendingEvent);
1973 assert(machine.myCurrentState);
1974
1977
1978 myCurrentState = getInstance(machine.myCurrentState->id());
1979 }
1980#endif
1981
1982} // namespace Macho
1983
1984#if defined(__clang__)
1985#if defined(_WIN32) || defined(_WIN64)
1986#pragma clang diagnostic pop
1987#endif
1988#endif
1989
1990
1991#endif // MACHO_HPP
Definition Macho.h:1490
_KeyData * key() const
Definition Macho.h:1558
Alias & operator=(const Alias &other)
Definition Macho.h:1516
Key myStateKey
Definition Macho.h:1562
bool isChild(Key k) const
Definition Macho.h:1536
~Alias()
Definition Macho.h:1527
Alias(Key key, _Initializer *init)
Definition Macho.h:1504
_Initializer * myInitializer
Definition Macho.h:1565
void setState(_MachineBase &machine) const
Alias(const Alias &other)
Definition Macho.h:1511
ID id() const
Definition Macho.h:1548
bool isParent(Key k) const
Definition Macho.h:1540
const char * name() const
Definition Macho.h:1544
Alias(Key key, bool history=false)
Definition Macho.h:1492
Definition Macho.h:860
Definition Macho.h:1656
Machine()
Definition Macho.h:1676
~Machine() override
Definition Macho.h:1727
void dispatch(IEvent< TOP > *event, bool destroy=true)
Definition Macho.h:1744
const TOP::Box & box() const
Definition Macho.h:1754
AfterAdvice operator->()
Definition Macho.h:1735
Machine(const Alias &state)
Definition Macho.h:1688
Definition Macho.h:626
static const ID value
Definition Macho.h:628
Definition Macho.h:514
T TOP
Definition Macho.h:517
TopBase(_StateInstance &instance)
Definition Macho.h:520
void dispatch(IEvent< TOP > *event)
Definition Macho.h:1872
const Machine< TOP > & machine()
Definition Macho.h:1879
Definition Macho.h:1190
_Initializer * clone() override
Definition Macho.h:1198
const _MachineBase & myMachine
Definition Macho.h:1205
_AdaptingInitializer(const _MachineBase &machine)
Definition Macho.h:1192
void execute(_StateInstance &instance) override
Definition Macho.h:1194
Key adapt(Key key) override
Definition Macho.h:1171
void execute(_StateInstance &instance) override
Definition Macho.h:1173
Definition Macho.h:319
static _EmptyBox theEmptyBox
Definition Macho.h:321
Definition Macho.h:1030
void dispatch(_StateInstance &instance) override
Definition Macho.h:1039
_Event0(Signature handler)
Definition Macho.h:1034
Signature myHandler
Definition Macho.h:1044
Definition Macho.h:1008
Signature myHandler
Definition Macho.h:1023
_Event1(Signature handler, const P1 &p1)
Definition Macho.h:1012
P1 myParam1
Definition Macho.h:1024
void dispatch(_StateInstance &instance) override
Definition Macho.h:1018
Definition Macho.h:984
P1 myParam1
Definition Macho.h:1001
P2 myParam2
Definition Macho.h:1002
_Event2(Signature handler, const P1 &p1, const P2 &p2)
Definition Macho.h:988
Signature myHandler
Definition Macho.h:1000
void dispatch(_StateInstance &instance)
Definition Macho.h:995
Definition Macho.h:958
P3 myParam3
Definition Macho.h:978
_Event3(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3)
Definition Macho.h:962
P1 myParam1
Definition Macho.h:976
Signature myHandler
Definition Macho.h:975
void dispatch(_StateInstance &instance)
Definition Macho.h:970
P2 myParam2
Definition Macho.h:977
Definition Macho.h:930
void dispatch(_StateInstance &instance)
Definition Macho.h:943
_Event4(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
Definition Macho.h:934
P4 myParam4
Definition Macho.h:952
P2 myParam2
Definition Macho.h:950
P1 myParam1
Definition Macho.h:949
Signature myHandler
Definition Macho.h:948
P3 myParam3
Definition Macho.h:951
Definition Macho.h:900
P1 myParam1
Definition Macho.h:920
P2 myParam2
Definition Macho.h:921
P4 myParam4
Definition Macho.h:923
Signature myHandler
Definition Macho.h:919
_Event5(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
Definition Macho.h:904
P5 myParam5
Definition Macho.h:924
P3 myParam3
Definition Macho.h:922
void dispatch(_StateInstance &instance)
Definition Macho.h:914
Definition Macho.h:868
void dispatch(_StateInstance &instance)
Definition Macho.h:883
_Event6(Signature handler, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
Definition Macho.h:872
P3 myParam3
Definition Macho.h:891
P4 myParam4
Definition Macho.h:892
P1 myParam1
Definition Macho.h:889
P6 myParam6
Definition Macho.h:894
Signature myHandler
Definition Macho.h:888
P5 myParam5
Definition Macho.h:893
P2 myParam2
Definition Macho.h:890
Definition Macho.h:1181
void execute(_StateInstance &instance) override
Definition Macho.h:1183
Definition Macho.h:851
virtual void dispatch(_StateInstance &)=0
virtual ~_IEventBase()=default
Definition Macho.h:1211
void execute(_StateInstance &instance) override
Definition Macho.h:1221
P1 myParam1
Definition Macho.h:1226
_Initializer * clone() override
Definition Macho.h:1217
_Initializer1(const P1 &p1)
Definition Macho.h:1213
Definition Macho.h:1231
_Initializer2(const P1 &p1, const P2 &p2)
Definition Macho.h:1233
_Initializer * clone() override
Definition Macho.h:1238
void execute(_StateInstance &instance) override
Definition Macho.h:1242
P1 myParam1
Definition Macho.h:1247
P2 myParam2
Definition Macho.h:1248
Definition Macho.h:1253
P1 myParam1
Definition Macho.h:1270
P2 myParam2
Definition Macho.h:1271
_Initializer * clone() override
Definition Macho.h:1261
_Initializer3(const P1 &p1, const P2 &p2, const P3 &p3)
Definition Macho.h:1255
void execute(_StateInstance &instance) override
Definition Macho.h:1265
P3 myParam3
Definition Macho.h:1272
Definition Macho.h:1277
_Initializer * clone() override
Definition Macho.h:1286
P3 myParam3
Definition Macho.h:1297
_Initializer4(const P1 &p1, const P2 &p2, const P3 &p3, P4 &p4)
Definition Macho.h:1279
P1 myParam1
Definition Macho.h:1295
P2 myParam2
Definition Macho.h:1296
P4 myParam4
Definition Macho.h:1298
void execute(_StateInstance &instance) override
Definition Macho.h:1290
Definition Macho.h:1303
P3 myParam3
Definition Macho.h:1324
P4 myParam4
Definition Macho.h:1325
_Initializer5(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
Definition Macho.h:1305
P5 myParam5
Definition Macho.h:1326
void execute(_StateInstance &instance) override
Definition Macho.h:1317
P1 myParam1
Definition Macho.h:1322
P2 myParam2
Definition Macho.h:1323
_Initializer * clone() override
Definition Macho.h:1313
Definition Macho.h:1331
P1 myParam1
Definition Macho.h:1351
P2 myParam2
Definition Macho.h:1352
_Initializer * clone() override
Definition Macho.h:1342
P6 myParam6
Definition Macho.h:1356
P4 myParam4
Definition Macho.h:1354
_Initializer6(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
Definition Macho.h:1333
void execute(_StateInstance &instance) override
Definition Macho.h:1346
P3 myParam3
Definition Macho.h:1353
P5 myParam5
Definition Macho.h:1355
Definition Macho.h:1142
virtual ~_Initializer()=default
virtual Key adapt(Key key)
Definition Macho.h:1152
virtual _Initializer * clone()=0
virtual void execute(_StateInstance &instance)=0
virtual void destroy()
Definition Macho.h:1150
Definition Macho.h:1368
const _StateInstance * getInstance(ID id) const
Definition Macho.h:1410
_StateInstance * myPendingState
Definition Macho.h:1469
void allocate(unsigned int count)
void * myPendingBox
Definition Macho.h:1473
void setState(_StateInstance &instance, _Initializer *init)
friend class _StateInstance
Definition Macho.h:1460
class Alias currentState() const
_StateInstance *& getInstance(ID id)
Definition Macho.h:1405
void start(const Alias &state)
_Initializer * myPendingInit
Definition Macho.h:1470
void setPendingEvent(_IEventBase *event)
Definition Macho.h:1394
virtual ~_MachineBase()
void start(_StateInstance &instance)
void setState(const Alias &state)
_StateInstance * myCurrentState
Definition Macho.h:1466
void free(unsigned int count)
void setPendingState(_StateInstance &instance, _Initializer *init)
Definition Macho.h:1385
_IEventBase * myPendingEvent
Definition Macho.h:1475
_StateInstance ** myInstances
Definition Macho.h:1478
void clearHistoryDeep(unsigned int count, const _StateInstance &instance) const
Definition Macho.h:750
_RootInstance(_MachineBase &machine, _StateInstance *parent)
Definition Macho.h:754
const char * name() override
Definition Macho.h:776
void deleteBox() override
Definition Macho.h:771
ID id() override
Definition Macho.h:761
friend class _StateSpecification
Definition Macho.h:752
Key key() override
Definition Macho.h:765
void createBox() override
Definition Macho.h:770
_StateInstance * create(_MachineBase &machine, _StateInstance *parent) override
Definition Macho.h:779
Definition Macho.h:637
virtual _StateInstance * create(_MachineBase &machine, _StateInstance *parent)=0
void setBox(void *box)
Definition Macho.h:698
void exit(_StateInstance &next)
virtual void deleteBox()=0
void * myBoxPlace
Definition Macho.h:744
void setHistory(_StateInstance *history) const
Definition Macho.h:730
void shutdown()
Definition Macho.h:674
_MachineBase & machine()
Definition Macho.h:725
void entry(_StateInstance &previous, bool first=true)
void setHistorySuper(_StateInstance &deep)
Definition Macho.h:660
_StateInstance * myHistory
Definition Macho.h:741
bool isChild(const _StateInstance &instance)
Definition Macho.h:711
void init(bool history)
virtual const char * name()=0
_MachineBase & myMachine
Definition Macho.h:739
void * box()
Definition Macho.h:720
_StateInstance(_MachineBase &machine, _StateInstance *parent)
void restore(_StateInstance &instance)
Definition Macho.h:678
virtual Key key()=0
_StateSpecification & specification()
Definition Macho.h:715
void * myBox
Definition Macho.h:743
virtual void createBox()=0
void saveHistory(_StateInstance &shallow, _StateInstance &deep)
Definition Macho.h:654
_StateInstance * myParent
Definition Macho.h:742
_StateSpecification * mySpecification
Definition Macho.h:740
virtual ID id()=0
_StateInstance * history() const
Definition Macho.h:734
Definition Macho.h:394
static bool isChild(Key)
Definition Macho.h:398
friend class _StateInstance
Definition Macho.h:493
void setStateDirect(typename S::Box *box=0)
Definition Macho.h:1861
virtual void _setHistorySuper(_StateInstance &, _StateInstance &)
Definition Macho.h:466
void setStateBox(typename S::Box *box=0)
Definition Macho.h:1852
void setState(const class Alias &state)
void setState(_StateInstance &current)
void setStateHistory()
Definition Macho.h:1844
virtual void _restore(_StateInstance &current)
virtual ~_StateSpecification()=default
void setState()
Definition Macho.h:1794
_StateSpecification(_StateInstance &instance)
Definition Macho.h:403
Definition Macho.h:1160
Definition Macho.h:790
_StateInstance * create(_MachineBase &machine, _StateInstance *parent) override
Definition Macho.h:821
Key key() override
Definition Macho.h:816
const char * name() override
Definition Macho.h:810
typename S::Box Box
Definition Macho.h:803
ID id() override
Definition Macho.h:812
void deleteBox() override
Definition Macho.h:830
_SubstateInstance(_MachineBase &machine, _StateInstance *parent)
Definition Macho.h:795
void createBox() override
Definition Macho.h:825
~_SubstateInstance() override
Definition Macho.h:805
Definition Macho.h:1093
static void execute(Macho::_StateInstance &instance, const P1 &p1)
Definition Macho.h:1096
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:1126
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
Definition Macho.h:1114
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2)
Definition Macho.h:1102
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
Definition Macho.h:1120
static void execute(Macho::_StateInstance &instance, const P1 &p1, const P2 &p2, const P3 &p3)
Definition Macho.h:1108
Definition Macho.h:297
void _deleteBox< _EmptyBox >(void *&box, void *&place)
void * _createBox< _EmptyBox >(void *&place)
static _HistoryInitializer _theHistoryInitializer
Definition Macho.h:1363
void * Key
Definition Macho.h:310
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:1050
void * _createBox(void *&place)
Definition Macho.h:328
Alias StateHistory(const _MachineBase &machine)
Definition Macho.h:1612
static _DefaultInitializer _theDefaultInitializer
Definition Macho.h:1362
Alias State()
Definition Macho.h:1574
void _deleteBox(void *&box, void *&place)
Definition Macho.h:341
unsigned int ID
Definition Macho.h:314
bool Check
Definition Macho.h:227
Definition Macho.h:222
Definition Macho.h:1661
TOP * operator->()
Definition Macho.h:1668
~AfterAdvice()
Definition Macho.h:1665
AfterAdvice(Machine< TOP > &m)
Definition Macho.h:1662
Definition Macho.h:374
const NameFn name
Definition Macho.h:385
const Generator instanceGenerator
Definition Macho.h:380
const char *(*)() NameFn
Definition Macho.h:377
bool(*)(Key) Predicate
Definition Macho.h:376
_StateInstance &(*)(_MachineBase &) Generator
Definition Macho.h:375
const ID id
Definition Macho.h:386
const Predicate childPredicate
Definition Macho.h:383