From ed1a9ef84d8157d74fb2c30c9f91ea0fd60d04e1 Mon Sep 17 00:00:00 2001 From: Andrew Gresyk Date: Sat, 16 May 2020 09:22:15 +0300 Subject: [PATCH] + added serialization support --- README.md | 23 +- examples/snippets/docs_serialization.cpp | 50 + examples/snippets/main.cpp | 2 +- examples/snippets/wiki_plans.cpp | 2 +- .../wiki_transitions-within-hierarchy.cpp | 2 +- examples/snippets/wiki_tutorial.cpp | 2 +- examples/snippets/wiki_utility-theory.cpp | 2 +- include/hfsm2/detail/root.hpp | 106 +- include/hfsm2/detail/root.inl | 104 +- include/hfsm2/detail/root/control.hpp | 32 +- include/hfsm2/detail/root/plan_data.hpp | 4 + include/hfsm2/detail/root/plan_data.inl | 8 +- .../root/{state_registry.hpp => registry.hpp} | 123 +- include/hfsm2/detail/root/registry.inl | 388 ++++ include/hfsm2/detail/root/state_registry.inl | 371 ---- include/hfsm2/detail/shared/array.hpp | 3 +- include/hfsm2/detail/shared/bit_array.inl | 1 + include/hfsm2/detail/shared/bit_stream.hpp | 73 + include/hfsm2/detail/shared/bit_stream.inl | 94 + include/hfsm2/detail/shared/random.inl | 17 - include/hfsm2/detail/shared/utility.hpp | 70 +- include/hfsm2/detail/structure/composite.hpp | 81 +- include/hfsm2/detail/structure/composite.inl | 143 +- .../hfsm2/detail/structure/composite_sub.hpp | 64 +- .../detail/structure/composite_sub_1.inl | 84 +- .../detail/structure/composite_sub_2.inl | 66 +- include/hfsm2/detail/structure/forward.hpp | 133 +- include/hfsm2/detail/structure/orthogonal.hpp | 57 +- include/hfsm2/detail/structure/orthogonal.inl | 74 +- .../hfsm2/detail/structure/orthogonal_sub.hpp | 68 +- .../detail/structure/orthogonal_sub_1.inl | 72 +- .../detail/structure/orthogonal_sub_2.inl | 60 +- include/hfsm2/detail/structure/state.hpp | 35 +- include/hfsm2/detail/structure/state.inl | 4 +- include/hfsm2/machine.hpp | 1752 ++++++++++++----- include/hfsm2/machine_dev.hpp | 5 +- .../snippets-gcc-tdm/snippets-gcc-tdm.project | 11 +- .../test-gcc-tdm/test-gcc-tdm.project | 31 +- projects/visual-studio/snippets-14.vcxproj | 1 + .../visual-studio/snippets-14.vcxproj.filters | 1 + projects/visual-studio/snippets-15.vcxproj | 1 + .../visual-studio/snippets-15.vcxproj.filters | 1 + projects/visual-studio/snippets-16.vcxproj | 1 + .../visual-studio/snippets-16.vcxproj.filters | 1 + projects/visual-studio/snippets-clang.vcxproj | 1 + .../snippets-clang.vcxproj.filters | 1 + projects/visual-studio/test-14.vcxproj | 8 +- .../visual-studio/test-14.vcxproj.filters | 24 +- projects/visual-studio/test-15.vcxproj | 8 +- .../visual-studio/test-15.vcxproj.filters | 24 +- projects/visual-studio/test-16.vcxproj | 8 +- .../visual-studio/test-16.vcxproj.filters | 24 +- projects/visual-studio/test-clang.vcxproj | 8 +- .../visual-studio/test-clang.vcxproj.filters | 24 +- test/shared/test_bit_array.cpp | 2 +- test/shared/test_bit_stream.cpp | 35 + test/test_replication.cpp | 12 + test/test_serialization.cpp | 315 +++ 58 files changed, 3395 insertions(+), 1322 deletions(-) create mode 100644 examples/snippets/docs_serialization.cpp rename include/hfsm2/detail/root/{state_registry.hpp => registry.hpp} (61%) create mode 100644 include/hfsm2/detail/root/registry.inl delete mode 100644 include/hfsm2/detail/root/state_registry.inl create mode 100644 include/hfsm2/detail/shared/bit_stream.hpp create mode 100644 include/hfsm2/detail/shared/bit_stream.inl create mode 100644 test/shared/test_bit_stream.cpp create mode 100644 test/test_serialization.cpp diff --git a/README.md b/README.md index 6bbc6b0..67fd59b 100644 --- a/README.md +++ b/README.md @@ -11,21 +11,23 @@ Header-only heriarchical FSM framework in C++14, with fully statically-defined s - Visual Studio 14, 15, 16 - GCC 5, 6, 7, 8, 9 -- Clang 3.7, 3.8, 3.9, 4, 5, 6, 7, 8 +- Clang 3.7, 3.8, 3.9, 4, 5, 6, 7, 8, 9, 10 --- -## Tutorial +## Documentation -Check [Wiki](https://github.com/andrew-gresyk/HFSM2/wiki/Tutorial) for basic usage and more info. +[Old Wiki](https://github.com/andrew-gresyk/HFSM2/wiki/Tutorial) docs are being upgraded and moved to the [New GitBook](https://doc.hfsm.dev/). +In-line comment-based docs is an on-going effort. --- ## Feature Highlights - Permissive [MIT License](https://github.com/andrew-gresyk/HFSM2/blob/master/LICENSE) -- Written in widely-supported modern(ish) C++14 +- Written in widely-supported modern(ish) C++11 - Header-only +- Convenient, minimal boilerplate - Fully static, no dynamic allocations - Uses inline-friendly compile-time pylymorphism, no virtual methods were harmed - Type-safe transitions: `FSM.changeTo()` @@ -33,12 +35,12 @@ Check [Wiki](https://github.com/andrew-gresyk/HFSM2/wiki/Tutorial) for basic usa - [Hierarchical](https://github.com/andrew-gresyk/HFSM2/wiki/Transitions-within-Hierarchy), with a selection of composite (sub-machine) and orthogonal regions - Gamedev-friendly, supports explicit `State::update()` - Also supports traditional event-based workflow with `State::react()` -- [Dynamic planning](https://github.com/andrew-gresyk/HFSM2/wiki/Plans) support +- AI-friendly with [Dynamic planning](https://github.com/andrew-gresyk/HFSM2/wiki/Plans) support - [Utility theory](https://github.com/andrew-gresyk/HFSM2/wiki/Utility-Theory) support (both max score and ranked weighted random) - Scaleable, supports robust state re-use via state injections - [Debug-assisted](https://gresyk.dev/features/2018/01/15/hfsm-magic.html), includes automatic structure and activity visualization API with `#define HFSM_ENABLE_STRUCTURE_REPORT` +- [Serializable](https://doc.hfsm.dev/user-guide/debugging-and-tools/serialization), with activity and transition history support - Built-in logging support -- Convenient, minimal boilerplate --- @@ -56,6 +58,15 @@ Check [Wiki](https://github.com/andrew-gresyk/HFSM2/wiki/Tutorial) for basic usa --- +## Get In Touch + +Please share your comments and suggestions on: + +- [Gitter](https://gitter.im/andrew-gresyk/HFSM2) +- [Twitter](https://www.twitter.com/andrew_gresyk) + +--- + ## Special Thanks - [Kevin Greene](https://github.com/kgreenek) diff --git a/examples/snippets/docs_serialization.cpp b/examples/snippets/docs_serialization.cpp new file mode 100644 index 0000000..ee726b5 --- /dev/null +++ b/examples/snippets/docs_serialization.cpp @@ -0,0 +1,50 @@ +// HFSM2 (hierarchical state machine for games and interactive applications) +// Created by Andrew Gresyk + +#define HFSM_ENABLE_SERIALIZATION + +//#include +#include + +#include +#undef assert +#define assert(x) REQUIRE(x) + +using M = hfsm2::Machine; + +using FSM = M::PeerRoot< + struct State1, + struct State2 +>; + +struct State1 : FSM::State { /* .. */ }; +struct State2 : FSM::State { /* .. */ }; + +//------------------------------------------------------------------------------ + +TEST_CASE("Docs.Serialization", "[Docs]") { + // Buffer for serialization + // Members: + // bitSize - Number of payload bits used + // payload - Serialized data + FSM::Instance::SerialBuffer buffer; + + { + FSM::Instance fsm; // Create a new FSM instance + fsm.changeTo(); // Request a transition to 'State2' + fsm.update(); // Process transitions + assert(fsm.isActive()); // Check if transition completed + + fsm.save(buffer); // Serialize FSM configuration into 'buffer' + } + + { + FSM::Instance fsm; // Create a fresh FSM instance + assert(fsm.isActive()); // Initial 'State1' is activated by default + + fsm.load(buffer); // De-serialize FSM from 'buffer' + assert(fsm.isActive()); // Check its configuration is restored + } +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/examples/snippets/main.cpp b/examples/snippets/main.cpp index d799c0d..7455fd2 100644 --- a/examples/snippets/main.cpp +++ b/examples/snippets/main.cpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk #define CATCH_CONFIG_MAIN diff --git a/examples/snippets/wiki_plans.cpp b/examples/snippets/wiki_plans.cpp index 099459d..f33dc15 100644 --- a/examples/snippets/wiki_plans.cpp +++ b/examples/snippets/wiki_plans.cpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk #include diff --git a/examples/snippets/wiki_transitions-within-hierarchy.cpp b/examples/snippets/wiki_transitions-within-hierarchy.cpp index 5a150f9..5c8a91a 100644 --- a/examples/snippets/wiki_transitions-within-hierarchy.cpp +++ b/examples/snippets/wiki_transitions-within-hierarchy.cpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk #include diff --git a/examples/snippets/wiki_tutorial.cpp b/examples/snippets/wiki_tutorial.cpp index 91e303f..ab7e37a 100644 --- a/examples/snippets/wiki_tutorial.cpp +++ b/examples/snippets/wiki_tutorial.cpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk #include diff --git a/examples/snippets/wiki_utility-theory.cpp b/examples/snippets/wiki_utility-theory.cpp index 12bc334..299f102 100644 --- a/examples/snippets/wiki_utility-theory.cpp +++ b/examples/snippets/wiki_utility-theory.cpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk #define HFSM_ENABLE_LOG_INTERFACE diff --git a/include/hfsm2/detail/root.hpp b/include/hfsm2/detail/root.hpp index 398a43f..da615c7 100644 --- a/include/hfsm2/detail/root.hpp +++ b/include/hfsm2/detail/root.hpp @@ -14,8 +14,8 @@ class R_ { using Logger = typename Config_::Logger; using Apex = TApex; - using ApexInfo = WrapInfo; + using Info = RF_; using StateList = typename Info::StateList; using RegionList = typename Info::RegionList; @@ -30,6 +30,9 @@ class R_ { static constexpr ShortIndex ORTHO_REGIONS = ApexInfo::ORTHO_REGIONS; static constexpr ShortIndex ORTHO_UNITS = ApexInfo::ORTHO_UNITS; + static constexpr LongIndex ACTIVE_BITS = ApexInfo::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = ApexInfo::RESUMABLE_BITS; + static constexpr LongIndex STATE_COUNT = ApexInfo::STATE_COUNT; static constexpr LongIndex REGION_COUNT = ApexInfo::REGION_COUNT; @@ -39,9 +42,9 @@ class R_ { private: using Args = typename Info::Args; - using StateRegistry = StateRegistryT; - using CompoForks = typename StateRegistry::CompoForks; - using AllForks = typename StateRegistry::AllForks; + using Registry = RegistryT; + using CompoForks = typename Registry::CompoForks; + using RegistryBackUp = typename Registry::BackUp; using MaterialApex = Material, Args, Apex>; @@ -55,23 +58,26 @@ class R_ { using GuardControl = GuardControlT; -public: - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_ENABLE_STRUCTURE_REPORT - using StructureStateInfos = typename Args::StructureStateInfos; - static constexpr LongIndex NAME_COUNT = MaterialApex::NAME_COUNT; using Prefix = StaticArray; using Prefixes = StaticArray; - using Structure = Array; - using ActivityHistory = Array; + using StructureStateInfos = typename Args::StructureStateInfos; #endif -#ifdef HFSM_ENABLE_TRANSITION_HISTORY - using TransitionHistory = Array; +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; +#endif + +public: + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_STRUCTURE_REPORT + using Structure = Array; + using ActivityHistory = Array; #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -86,10 +92,10 @@ class R_ { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - static constexpr StateID stateId() { return StateList ::template index(); } + static constexpr StateID stateId() { return StateList ::template index(); } template - static constexpr RegionID regionId() { return (RegionID) RegionList::template index(); } + static constexpr RegionID regionId() { return (RegionID) RegionList::template index(); } //---------------------------------------------------------------------- @@ -109,8 +115,8 @@ class R_ { template struct Accessor { - HFSM_INLINE static T& get( MaterialApex& apex) { return apex.template access(); } - HFSM_INLINE static const T& get(const MaterialApex& apex) { return apex.template access(); } + HFSM_INLINE static T& get( MaterialApex& apex) { return apex.template access(); } + HFSM_INLINE static const T& get(const MaterialApex& apex) { return apex.template access(); } }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -122,20 +128,20 @@ class R_ { // .. you're trying to access() a type that is not present in the state machine hierarchy template - HFSM_INLINE T& access() { return Accessor::get(_apex); } + HFSM_INLINE T& access() { return Accessor::get(_apex); } template - HFSM_INLINE const T& access() const { return Accessor::get(_apex); } + HFSM_INLINE const T& access() const { return Accessor::get(_apex); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #else template - HFSM_INLINE T& access() { return Accessor{_apex}.get(); } + HFSM_INLINE T& access() { return Accessor{_apex}.get(); } template - HFSM_INLINE const T& access() const { return Accessor{_apex}.get(); } + HFSM_INLINE const T& access() const { return Accessor{_apex}.get(); } #endif @@ -148,19 +154,19 @@ class R_ { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE bool isActive (const StateID stateId) const { return _stateRegistry.isActive (stateId); } - HFSM_INLINE bool isResumable(const StateID stateId) const { return _stateRegistry.isResumable(stateId); } + HFSM_INLINE bool isActive (const StateID stateId) const { return _registry.isActive (stateId); } + HFSM_INLINE bool isResumable(const StateID stateId) const { return _registry.isResumable(stateId); } - HFSM_INLINE bool isScheduled(const StateID stateId) const { return isResumable(stateId); } + HFSM_INLINE bool isScheduled(const StateID stateId) const { return isResumable(stateId); } template - HFSM_INLINE bool isActive () const { return isActive (stateId()); } + HFSM_INLINE bool isActive () const { return isActive (stateId()); } template - HFSM_INLINE bool isResumable() const { return isResumable(stateId()); } + HFSM_INLINE bool isResumable() const { return isResumable(stateId()); } template - HFSM_INLINE bool isScheduled() const { return isResumable(); } + HFSM_INLINE bool isScheduled() const { return isResumable(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -174,42 +180,58 @@ class R_ { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - HFSM_INLINE void changeTo () { changeTo (stateId()); } + HFSM_INLINE void changeTo () { changeTo (stateId()); } template - HFSM_INLINE void restart () { restart (stateId()); } + HFSM_INLINE void restart () { restart (stateId()); } template - HFSM_INLINE void resume () { resume (stateId()); } + HFSM_INLINE void resume () { resume (stateId()); } template - HFSM_INLINE void utilize () { utilize (stateId()); } + HFSM_INLINE void utilize () { utilize (stateId()); } template - HFSM_INLINE void randomize() { randomize(stateId()); } + HFSM_INLINE void randomize() { randomize(stateId()); } template - HFSM_INLINE void schedule () { schedule (stateId()); } + HFSM_INLINE void schedule () { schedule (stateId()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void clearResumable() { _stateRegistry.resumable.clear(); } - HFSM_INLINE void clearRequests() { _stateRegistry.requested.clear(); } - #ifdef HFSM_ENABLE_STRUCTURE_REPORT - const Structure& structure() const { return _structure; } - const ActivityHistory& activityHistory() const { return _activityHistory; } + const Structure& structure() const { return _structure; } + const ActivityHistory& activityHistory() const { return _activityHistory; } #endif #ifdef HFSM_ENABLE_TRANSITION_HISTORY - const TransitionHistory& transitionHistory() const { return _transitionHistory; } + using TransitionHistory = Array; + + const TransitionHistory& transitionHistory() const { return _transitionHistory; } - void replayTransition (const Transition& transition) { replayTransitions(&transition, 1); } + void replayTransition (const Transition& transition) { replayTransitions(&transition, 1); } void replayTransitions(const Transition* const transitions, const uint64_t count); #endif + void reset(); + +#ifdef HFSM_ENABLE_SERIALIZATION + // Buffer for serialization + // Members: + // bitSize - Number of payload bits used + // payload - Serialized data + // See https://doc.hfsm.dev/user-guide/debugging-and-tools/serialization + using SerialBuffer = typename Args::SerialBuffer; + + // Serialize the structural configuration into 'buffer' + void save( SerialBuffer& buffer) const; + + // De-serialize the configuration and initialize the instance + void load(const SerialBuffer& buffer); +#endif + #if defined HFSM_ENABLE_LOG_INTERFACE || defined HFSM_ENABLE_VERBOSE_DEBUG_LOG - void attachLogger(Logger* const logger) { _logger = logger; } + void attachLogger(Logger* const logger) { _logger = logger; } #endif private: @@ -239,7 +261,7 @@ class R_ { Context& _context; RNG& _rng; - StateRegistry _stateRegistry; + Registry _registry; PlanData _planData; Requests _requests; diff --git a/include/hfsm2/detail/root.inl b/include/hfsm2/detail/root.inl index 21076ba..7892763 100644 --- a/include/hfsm2/detail/root.inl +++ b/include/hfsm2/detail/root.inl @@ -11,7 +11,7 @@ R_::R_(Context& context, , _rng{rng} HFSM_IF_LOGGER(, _logger{logger}) { - _apex.deepRegister(_stateRegistry, Parent{}); + _apex.deepRegister(_registry, Parent{}); HFSM_IF_STRUCTURE(getStateNames()); @@ -24,7 +24,7 @@ template R_::~R_() { PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -41,7 +41,7 @@ void R_::update() { FullControl control(_context, _rng, - _stateRegistry, + _registry, _planData, _requests, HFSM_LOGGER_OR(_logger, nullptr)); @@ -63,7 +63,7 @@ void R_::react(const TEvent& event) { FullControl control{_context, _rng, - _stateRegistry, + _registry, _planData, _requests, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -151,14 +151,14 @@ R_::replayTransitions(const Transition* const transitions, PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; if (applyRequests(control, transitions, count)) { _apex.deepChangeToRequested(control); - _stateRegistry.clearRequests(); + _registry.clearRequests(); HFSM_IF_ASSERT(_planData.verifyPlans()); } @@ -171,21 +171,76 @@ R_::replayTransitions(const Transition* const transitions, //------------------------------------------------------------------------------ +template +void +R_::reset() { + PlanControl control{_context, + _rng, + _registry, + _planData, + HFSM_LOGGER_OR(_logger, nullptr)}; + + _apex.deepExit (control); + _apex.deepDestruct (control); + + _registry.reset(); + + _apex.deepRequestChange(control); + _apex.deepConstruct(control); + _apex.deepEnter (control); +} + +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +R_::save(SerialBuffer& _buffer) const { + WriteStream stream{_buffer}; + + _apex.deepSaveActive(_registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +R_::load(const SerialBuffer& buffer) { + PlanControl control{_context, + _rng, + _registry, + _planData, + HFSM_LOGGER_OR(_logger, nullptr)}; + + _apex.deepExit (control); + _apex.deepDestruct (control); + + ReadStream stream{buffer}; + _apex.deepLoadRequested(_registry, stream); + + _apex.deepConstruct(control); + _apex.deepEnter (control); +} + +#endif + +//------------------------------------------------------------------------------ + template void R_::initialEnter() { HFSM_ASSERT(_requests.count() == 0); HFSM_IF_TRANSITION_HISTORY(HFSM_ASSERT(_transitionHistory.count() == 0)); - CompoForks undoResumable; - AllForks undoRequested; + RegistryBackUp undo; HFSM_IF_TRANSITION_HISTORY(TransitionHistory undoTransitionHistory); Requests lastRequests; PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -197,8 +252,7 @@ R_::initialEnter() { i < SUBSTITUTION_LIMIT && _requests.count(); ++i) { - undoResumable = _stateRegistry.resumable; - undoRequested = _stateRegistry.requested; + backup(_registry, undo); HFSM_IF_TRANSITION_HISTORY(undoTransitionHistory = _transitionHistory); if (applyRequests(control)) { @@ -206,8 +260,7 @@ R_::initialEnter() { _requests.clear(); if (cancelledByEntryGuards(lastRequests)) { - _stateRegistry.resumable = undoResumable; - _stateRegistry.requested = undoRequested; + restore(_registry, undo); HFSM_IF_TRANSITION_HISTORY(_transitionHistory = undoTransitionHistory); } } else @@ -218,7 +271,7 @@ R_::initialEnter() { _apex.deepConstruct(control); _apex.deepEnter (control); - _stateRegistry.clearRequests(); + _registry.clearRequests(); HFSM_IF_ASSERT(_planData.verifyPlans()); @@ -234,15 +287,14 @@ R_::processTransitions() { HFSM_IF_TRANSITION_HISTORY(_transitionHistory.clear()); - CompoForks undoResumable; - AllForks undoRequested; + RegistryBackUp undo; HFSM_IF_TRANSITION_HISTORY(TransitionHistory undoTransitionHistory); Requests lastRequests; PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -252,8 +304,7 @@ R_::processTransitions() { i < SUBSTITUTION_LIMIT && _requests.count(); ++i) { - undoResumable = _stateRegistry.resumable; - undoRequested = _stateRegistry.requested; + backup(_registry, undo); HFSM_IF_TRANSITION_HISTORY(undoTransitionHistory = _transitionHistory); if (applyRequests(control)) { @@ -261,8 +312,7 @@ R_::processTransitions() { _requests.clear(); if (cancelledByGuards(lastRequests)) { - _stateRegistry.resumable = undoResumable; - _stateRegistry.requested = undoRequested; + restore(_registry, undo); HFSM_IF_TRANSITION_HISTORY(_transitionHistory = undoTransitionHistory); } else changesMade = true; @@ -273,7 +323,7 @@ R_::processTransitions() { if (changesMade) { _apex.deepChangeToRequested(control); - _stateRegistry.clearRequests(); + _registry.clearRequests(); HFSM_IF_ASSERT(_planData.verifyPlans()); } @@ -294,7 +344,7 @@ R_::applyRequest(Control& control, const Request& request) { case Request::RESUME: case Request::UTILIZE: case Request::RANDOMIZE: - if (_stateRegistry.requestImmediate(request)) + if (_registry.requestImmediate(request)) _apex.deepForwardActive(control, request.type); else _apex.deepRequest (control, request.type); @@ -302,7 +352,7 @@ R_::applyRequest(Control& control, const Request& request) { return true; case Request::SCHEDULE: - _stateRegistry.requestScheduled(request.stateId); + _registry.requestScheduled(request.stateId); return false; @@ -356,7 +406,7 @@ bool R_::cancelledByEntryGuards(const Requests& pendingRequests) { GuardControl guardControl{_context, _rng, - _stateRegistry, + _registry, _planData, _requests, pendingRequests, @@ -377,7 +427,7 @@ bool R_::cancelledByGuards(const Requests& pendingRequests) { GuardControl guardControl{_context, _rng, - _stateRegistry, + _registry, _planData, _requests, pendingRequests, @@ -504,7 +554,7 @@ R_::udpateActivity() { #endif -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +//------------------------------------------------------------------------------ #ifdef HFSM_ENABLE_TRANSITION_HISTORY diff --git a/include/hfsm2/detail/root/control.hpp b/include/hfsm2/detail/root/control.hpp index 47b1d28..b8e65aa 100644 --- a/include/hfsm2/detail/root/control.hpp +++ b/include/hfsm2/detail/root/control.hpp @@ -28,7 +28,7 @@ class ControlT { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; + using Registry = RegistryT; using PlanData = PlanDataT; using ConstPlan = ConstPlanT; @@ -48,12 +48,12 @@ class ControlT { HFSM_INLINE ControlT(Context& context, RNG& rng, - StateRegistry& stateRegistry, + Registry& registry, PlanData& planData, Logger* const HFSM_IF_LOGGER(logger)) : _context{context} , _rng{rng} - , _stateRegistry{stateRegistry} + , _registry{registry} , _planData{planData} HFSM_IF_LOGGER(, _logger{logger}) {} @@ -74,8 +74,8 @@ class ControlT { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE bool isActive (const StateID id) const { return _stateRegistry.isActive (id); } - HFSM_INLINE bool isResumable(const StateID id) const { return _stateRegistry.isResumable(id); } + HFSM_INLINE bool isActive (const StateID id) const { return _registry.isActive (id); } + HFSM_INLINE bool isResumable(const StateID id) const { return _registry.isResumable(id); } HFSM_INLINE bool isScheduled(const StateID id) const { return isResumable(id); } @@ -107,7 +107,7 @@ class ControlT { protected: Context& _context; RNG& _rng; - StateRegistry& _stateRegistry; + Registry& _registry; PlanData& _planData; RegionID _regionId = 0; HFSM_IF_LOGGER(Logger* _logger); @@ -252,7 +252,7 @@ class FullControlT using typename PlanControl::Plan; using typename PlanControl::Origin; - using StateRegistry = StateRegistryT; + using Registry = RegistryT; using Requests = RequestsT; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -268,11 +268,11 @@ class FullControlT HFSM_INLINE FullControlT(Context& context, RNG& rng, - StateRegistry& stateRegistry, + Registry& registry, PlanData& planData, Requests& requests, Logger* const logger) - : PlanControl{context, rng, stateRegistry, planData, logger} + : PlanControl{context, rng, registry, planData, logger} , _requests{requests} {} @@ -368,7 +368,7 @@ class GuardControlT final using typename FullControl::RegionList; using typename FullControl::PlanData; - using typename FullControl::StateRegistry; + using typename FullControl::Registry; protected: using Requests = RequestsT; @@ -378,12 +378,12 @@ class GuardControlT final private: HFSM_INLINE GuardControlT(Context& context, RNG& rng, - StateRegistry& stateRegistry, + Registry& registry, PlanData& planData, Requests& requests, const Requests& pendingChanges, Logger* const logger) - : FullControl{context, rng, stateRegistry, planData, requests, logger} + : FullControl{context, rng, registry, planData, requests, logger} , _pending{pendingChanges} {} @@ -413,9 +413,9 @@ class GuardControlT final // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE bool isPendingChange(const StateID id) const { return _stateRegistry.isPendingChange(id); } - HFSM_INLINE bool isPendingEnter (const StateID id) const { return _stateRegistry.isPendingEnter (id); } - HFSM_INLINE bool isPendingExit (const StateID id) const { return _stateRegistry.isPendingExit (id); } + HFSM_INLINE bool isPendingChange(const StateID id) const { return _registry.isPendingChange(id); } + HFSM_INLINE bool isPendingEnter (const StateID id) const { return _registry.isPendingEnter (id); } + HFSM_INLINE bool isPendingExit (const StateID id) const { return _registry.isPendingExit (id); } template HFSM_INLINE bool isPendingChange() { return isPendingChange(FullControl::template stateId()); } @@ -435,7 +435,7 @@ class GuardControlT final private: HFSM_IF_LOGGER(using FullControl::_logger); - using FullControl::_stateRegistry; + using FullControl::_registry; using FullControl::_originId; bool _cancelled = false; diff --git a/include/hfsm2/detail/root/plan_data.hpp b/include/hfsm2/detail/root/plan_data.hpp index f5ce5d0..851b8bf 100644 --- a/include/hfsm2/detail/root/plan_data.hpp +++ b/include/hfsm2/detail/root/plan_data.hpp @@ -41,6 +41,7 @@ template struct ArgsT; @@ -56,6 +57,7 @@ template struct PlanDataT> { using StateList = TStateList; @@ -105,6 +108,7 @@ struct PlanDataT> { #ifdef HFSM_ENABLE_ASSERT diff --git a/include/hfsm2/detail/root/plan_data.inl b/include/hfsm2/detail/root/plan_data.inl index 109381c..ab6947f 100644 --- a/include/hfsm2/detail/root/plan_data.inl +++ b/include/hfsm2/detail/root/plan_data.inl @@ -5,9 +5,9 @@ namespace detail { #ifdef HFSM_ENABLE_ASSERT -template +template void -PlanDataT>::verifyPlans() const { +PlanDataT>::verifyPlans() const { LongIndex planCount = 0; for (RegionID id = 0; id < REGION_COUNT; ++id) planCount += verifyPlan(id); @@ -17,9 +17,9 @@ PlanDataT>::verifyPlans() co //------------------------------------------------------------------------------ -template +template LongIndex -PlanDataT>::verifyPlan(const RegionID regionId) const { +PlanDataT>::verifyPlan(const RegionID regionId) const { LongIndex length = 0; const Bounds& bounds = tasksBounds[regionId]; diff --git a/include/hfsm2/detail/root/state_registry.hpp b/include/hfsm2/detail/root/registry.hpp similarity index 61% rename from include/hfsm2/detail/root/state_registry.hpp rename to include/hfsm2/detail/root/registry.hpp index 46231c2..beac137 100644 --- a/include/hfsm2/detail/root/state_registry.hpp +++ b/include/hfsm2/detail/root/registry.hpp @@ -74,19 +74,14 @@ using RequestsT = Array; //////////////////////////////////////////////////////////////////////////////// -template -struct AllForksT { - static constexpr ShortIndex COMPO_REGIONS = NCompoCount; - static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; - static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; - - using Compo = StaticArray; - using Ortho = BitArray ; - - Compo compo{INVALID_SHORT_INDEX}; - Ortho ortho; - - HFSM_INLINE void clear(); +template +struct BackUpT { + using CompoForks = typename TRegistry::CompoForks; + using OrthoForks = typename TRegistry::OrthoForks; + + CompoForks compoRequested; + OrthoForks orthoRequested; + CompoForks compoResumable; }; //////////////////////////////////////////////////////////////////////////////// @@ -98,11 +93,12 @@ template struct ArgsT; template -struct StateRegistryT; +struct RegistryT; //------------------------------------------------------------------------------ @@ -113,23 +109,25 @@ template -struct StateRegistryT> +struct RegistryT> { using StateList = TStateList; using RegionList = TRegionList; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex COMPO_REGIONS = NCompoCount; - static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; - static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex COMPO_REGIONS = NCompoCount; + static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; + static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; using StateParents = StaticArray; @@ -138,10 +136,11 @@ struct StateRegistryT; using CompoForks = StaticArray; - using AllForks = AllForksT; - using OrthoBits = typename AllForks::Ortho::Bits; + using OrthoForks = BitArray ; + using OrthoBits = typename OrthoForks::Bits; + using CompoRemains = BitArray ; - using CompoRemains = BitArray; + using BackUp = BackUpT; bool isActive (const StateID stateId) const; bool isResumable (const StateID stateId) const; @@ -158,16 +157,18 @@ struct StateRegistryT -struct StateRegistryT> +struct RegistryT> { using StateList = TStateList; using RegionList = TRegionList; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex COMPO_REGIONS = NCompoCount; + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex COMPO_REGIONS = NCompoCount; using StateParents = StaticArray; using CompoParents = StaticArray; using CompoForks = StaticArray; - using AllForks = AllForksT; - using CompoRemains = BitArray; + using OrthoForks = BitArray ; + using CompoRemains = BitArray ; + + using BackUp = BackUpT; bool isActive (const StateID stateId) const; bool isResumable (const StateID stateId) const; @@ -214,20 +219,42 @@ struct StateRegistryT +void +backup(const TRegistry& registry, BackUpT& copy) { + overwrite(copy.compoRequested, registry.compoRequested); + overwrite(copy.orthoRequested, registry.orthoRequested); + overwrite(copy.compoResumable, registry.compoResumable); +} + +//------------------------------------------------------------------------------ + +template +void +restore(TRegistry& registry, const BackUpT& copy) { + overwrite(registry.compoRequested, copy.compoRequested); + overwrite(registry.orthoRequested, copy.orthoRequested); + overwrite(registry.compoResumable, copy.compoResumable); +} + +//////////////////////////////////////////////////////////////////////////////// + } } -#include "state_registry.inl" +#include "registry.inl" diff --git a/include/hfsm2/detail/root/registry.inl b/include/hfsm2/detail/root/registry.inl new file mode 100644 index 0000000..e71819c --- /dev/null +++ b/include/hfsm2/detail/root/registry.inl @@ -0,0 +1,388 @@ +#pragma once + +namespace hfsm2 { +namespace detail { + +//////////////////////////////////////////////////////////////////////////////// + +template +bool +RegistryT>::isActive(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + for (Parent parent = stateParents[stateId]; + parent; + parent = forkParent(parent.forkId)) + { + HFSM_ASSERT(parent.forkId != 0); + + if (parent.forkId > 0) + return parent.prong == compoActive[parent.forkId - 1]; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +bool +RegistryT>::isResumable(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + for (Parent parent = stateParents[stateId]; + parent; + parent = forkParent(parent.forkId)) + { + HFSM_ASSERT(parent.forkId != 0); + + if (parent.forkId > 0) + return parent.prong == compoResumable[parent.forkId - 1]; + } + + return false; +} + +//------------------------------------------------------------------------------ + +template +bool +RegistryT>::isPendingChange(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + for (Parent parent = stateParents[stateId]; + parent; + parent = forkParent(parent.forkId)) + { + HFSM_ASSERT(parent.forkId != 0); + + if (parent.forkId > 0) + return compoRequested[parent.forkId - 1] != + compoActive [parent.forkId - 1]; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +bool +RegistryT>::isPendingEnter(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + for (Parent parent = stateParents[stateId]; + parent; + parent = forkParent(parent.forkId)) + { + HFSM_ASSERT(parent.forkId != 0); + + if (parent.forkId > 0) + return parent.prong != compoActive [parent.forkId - 1] && + parent.prong == compoRequested[parent.forkId - 1]; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +bool +RegistryT>::isPendingExit(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + for (Parent parent = stateParents[stateId]; + parent; + parent = forkParent(parent.forkId)) + { + HFSM_ASSERT(parent.forkId != 0); + + if (parent.forkId > 0) + return parent.prong == compoActive [parent.forkId - 1] && + parent.prong != compoRequested[parent.forkId - 1]; + } + + return true; +} + +//------------------------------------------------------------------------------ + +template +const Parent& +RegistryT>::forkParent(const ForkID forkId) const { + HFSM_ASSERT(forkId != 0); + + return forkId > 0 ? + compoParents[ forkId - 1] : + orthoParents[-forkId - 1]; +} + +//------------------------------------------------------------------------------ + +template +typename RegistryT>::OrthoBits +RegistryT>::requestedOrthoFork(const ForkID forkId) { + HFSM_ASSERT(forkId < 0); + const Units& units = orthoUnits[-forkId - 1]; + + return orthoRequested.bits(units); +} + +//------------------------------------------------------------------------------ + +template +bool +RegistryT>::requestImmediate(const Request request) { + if (request.stateId == 0) + return false; + else if (HFSM_CHECKED(request.stateId < STATE_COUNT)) { + Parent parent; + + for (parent = stateParents[request.stateId]; + parent; + parent = forkParent(parent.forkId)) + { + if (parent.forkId > 0) { + compoRequested[parent.forkId - 1] = parent.prong; + parent = forkParent(parent.forkId); + + break; + } else if (parent.forkId < 0) + requestedOrthoFork(parent.forkId).set(parent.prong); + else + HFSM_BREAK(); + } + + for (; parent; parent = forkParent(parent.forkId)) { + if (parent.forkId > 0) { + compoRemains.set(parent.forkId - 1); + + if (compoActive [parent.forkId - 1] != parent.prong) + compoRequested[parent.forkId - 1] = parent.prong; + else { + parent = forkParent(parent.forkId); + break; + } + } else if (parent.forkId < 0) + requestedOrthoFork(parent.forkId).set(parent.prong); + else + HFSM_BREAK(); + } + + for (; parent; parent = forkParent(parent.forkId)) { + if (parent.forkId > 0) + compoRemains.set(parent.forkId - 1); + else if (parent.forkId < 0) + requestedOrthoFork(parent.forkId).set(parent.prong); + else + HFSM_BREAK(); + } + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +RegistryT>::requestScheduled(const StateID stateId) { + if (HFSM_CHECKED(stateId < STATE_COUNT)) { + const Parent parent = stateParents[stateId]; + + if (parent.forkId > 0) + compoResumable[parent.forkId - 1] = parent.prong; + else + HFSM_BREAK(); + } +} + +//------------------------------------------------------------------------------ + +template +void +RegistryT>::clearRequests() { + compoRequested.clear(); + orthoRequested.clear(); + compoRemains .clear(); +} + +//------------------------------------------------------------------------------ + +template +void +RegistryT>::reset() { + compoRequested.clear(); + orthoRequested.clear(); + compoActive .clear(); + compoResumable.clear(); + compoRemains .clear(); +} + +//////////////////////////////////////////////////////////////////////////////// + +template +bool +RegistryT>::isActive(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) { + if (Parent parent = stateParents[stateId]) { + HFSM_ASSERT(parent.forkId > 0); + + return parent.prong == compoActive[parent.forkId - 1]; + } else + return true; + } + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +bool +RegistryT>::isResumable(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + if (Parent parent = stateParents[stateId]) { + HFSM_ASSERT(parent.forkId > 0); + + return parent.prong == compoResumable[parent.forkId - 1]; + } + + return false; +} + +//------------------------------------------------------------------------------ + +template +bool +RegistryT>::isPendingChange(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + if (Parent parent = stateParents[stateId]) { + HFSM_ASSERT(parent.forkId > 0); + + return compoRequested[parent.forkId - 1] != + compoActive [parent.forkId - 1]; + } + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +bool +RegistryT>::isPendingEnter(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + if (Parent parent = stateParents[stateId]) { + HFSM_ASSERT(parent.forkId > 0); + + return parent.prong != compoActive [parent.forkId - 1] && + parent.prong == compoRequested[parent.forkId - 1]; + } + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +bool +RegistryT>::isPendingExit(const StateID stateId) const { + if (HFSM_CHECKED(stateId < STATE_COUNT)) + if (Parent parent = stateParents[stateId]) { + HFSM_ASSERT(parent.forkId > 0); + + return parent.prong == compoActive [parent.forkId - 1] && + parent.prong != compoRequested[parent.forkId - 1]; + } + + return false; +} + +//------------------------------------------------------------------------------ + +template +const Parent& +RegistryT>::forkParent(const ForkID forkId) const { + HFSM_ASSERT(forkId > 0); + + return compoParents[forkId - 1]; +} + +//------------------------------------------------------------------------------ + +template +bool +RegistryT>::requestImmediate(const Request request) { + if (request.stateId == 0) + return false; + else if (HFSM_CHECKED(request.stateId < STATE_COUNT)) { + Parent parent = stateParents[request.stateId]; + + if (HFSM_CHECKED(parent)) { + HFSM_ASSERT(parent.forkId > 0); + + compoRequested[parent.forkId - 1] = parent.prong; + + for (parent = forkParent(parent.forkId); + parent; + parent = forkParent(parent.forkId)) + { + HFSM_ASSERT(parent.forkId > 0); + compoRemains.set(parent.forkId - 1); + + if (compoActive [parent.forkId - 1] != parent.prong) + compoRequested[parent.forkId - 1] = parent.prong; + else { + parent = forkParent(parent.forkId); + break; + } + } + + for (; parent; parent = forkParent(parent.forkId)) { + HFSM_ASSERT(parent.forkId > 0); + compoRemains.set(parent.forkId - 1); + } + } + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +RegistryT>::requestScheduled(const StateID stateId) { + HFSM_ASSERT(stateId < STATE_COUNT); + + if (stateId < STATE_COUNT) { + const Parent parent = stateParents[stateId]; + + if (HFSM_CHECKED(parent.forkId > 0)) + compoResumable[parent.forkId - 1] = parent.prong; + } +} + +//------------------------------------------------------------------------------ + +template +void +RegistryT>::clearRequests() { + compoRequested.clear(); + orthoRequested.clear(); + compoRemains .clear(); +} + +//------------------------------------------------------------------------------ + +template +void +RegistryT>::reset() { + compoRequested.clear(); + orthoRequested.clear(); + compoActive .clear(); + compoResumable.clear(); + compoRemains .clear(); +} + +//////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/include/hfsm2/detail/root/state_registry.inl b/include/hfsm2/detail/root/state_registry.inl deleted file mode 100644 index 7e6204f..0000000 --- a/include/hfsm2/detail/root/state_registry.inl +++ /dev/null @@ -1,371 +0,0 @@ -#pragma once - -namespace hfsm2 { -namespace detail { - -//////////////////////////////////////////////////////////////////////////////// - -template -void -AllForksT::clear() { - compo.fill(INVALID_SHORT_INDEX); - ortho.clear(); -} - -//////////////////////////////////////////////////////////////////////////////// - -template -bool -StateRegistryT>::isActive(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - for (Parent parent = stateParents[stateId]; - parent; - parent = forkParent(parent.forkId)) - { - HFSM_ASSERT(parent.forkId != 0); - - if (parent.forkId > 0) - return parent.prong == compoActive[parent.forkId - 1]; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -bool -StateRegistryT>::isResumable(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - for (Parent parent = stateParents[stateId]; - parent; - parent = forkParent(parent.forkId)) - { - HFSM_ASSERT(parent.forkId != 0); - - if (parent.forkId > 0) - return parent.prong == resumable[parent.forkId - 1]; - } - - return false; -} - -//------------------------------------------------------------------------------ - -template -bool -StateRegistryT>::isPendingChange(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - for (Parent parent = stateParents[stateId]; - parent; - parent = forkParent(parent.forkId)) - { - HFSM_ASSERT(parent.forkId != 0); - - if (parent.forkId > 0) - return requested.compo[parent.forkId - 1] != - compoActive[parent.forkId - 1]; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -bool -StateRegistryT>::isPendingEnter(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - for (Parent parent = stateParents[stateId]; - parent; - parent = forkParent(parent.forkId)) - { - HFSM_ASSERT(parent.forkId != 0); - - if (parent.forkId > 0) - return parent.prong != compoActive[parent.forkId - 1] && - parent.prong == requested.compo[parent.forkId - 1]; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -bool -StateRegistryT>::isPendingExit(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - for (Parent parent = stateParents[stateId]; - parent; - parent = forkParent(parent.forkId)) - { - HFSM_ASSERT(parent.forkId != 0); - - if (parent.forkId > 0) - return parent.prong == compoActive[parent.forkId - 1] && - parent.prong != requested.compo[parent.forkId - 1]; - } - - return true; -} - -//------------------------------------------------------------------------------ - -template -const Parent& -StateRegistryT>::forkParent(const ForkID forkId) const { - HFSM_ASSERT(forkId != 0); - - return forkId > 0 ? - compoParents[ forkId - 1] : - orthoParents[-forkId - 1]; -} - -//------------------------------------------------------------------------------ - -template -typename StateRegistryT>::OrthoBits -StateRegistryT>::requestedOrthoFork(const ForkID forkId) { - HFSM_ASSERT(forkId < 0); - const Units& units = orthoUnits[-forkId - 1]; - - return requested.ortho.bits(units); -} - -//------------------------------------------------------------------------------ - -template -bool -StateRegistryT>::requestImmediate(const Request request) { - if (request.stateId == 0) - return false; - else if (HFSM_CHECKED(request.stateId < STATE_COUNT)) { - Parent parent; - - for (parent = stateParents[request.stateId]; - parent; - parent = forkParent(parent.forkId)) - { - if (parent.forkId > 0) { - requested.compo[parent.forkId - 1] = parent.prong; - parent = forkParent(parent.forkId); - - break; - } else if (parent.forkId < 0) - requestedOrthoFork(parent.forkId).set(parent.prong); - else - HFSM_BREAK(); - } - - for (; parent; parent = forkParent(parent.forkId)) { - if (parent.forkId > 0) { - compoRemains.set(parent.forkId - 1); - - if ( compoActive[parent.forkId - 1] != parent.prong) - requested.compo[parent.forkId - 1] = parent.prong; - else { - parent = forkParent(parent.forkId); - break; - } - } else if (parent.forkId < 0) - requestedOrthoFork(parent.forkId).set(parent.prong); - else - HFSM_BREAK(); - } - - for (; parent; parent = forkParent(parent.forkId)) { - if (parent.forkId > 0) - compoRemains.set(parent.forkId - 1); - else if (parent.forkId < 0) - requestedOrthoFork(parent.forkId).set(parent.prong); - else - HFSM_BREAK(); - } - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -void -StateRegistryT>::requestScheduled(const StateID stateId) { - if (HFSM_CHECKED(stateId < STATE_COUNT)) { - const Parent parent = stateParents[stateId]; - - if (parent.forkId > 0) - resumable[parent.forkId - 1] = parent.prong; - else - HFSM_BREAK(); - } -} - -//------------------------------------------------------------------------------ - -template -void -StateRegistryT>::clearRequests() { - compoRemains.clear(); - requested.clear(); -} - -//////////////////////////////////////////////////////////////////////////////// - -template -bool -StateRegistryT>::isActive(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) { - if (Parent parent = stateParents[stateId]) { - HFSM_ASSERT(parent.forkId > 0); - - return parent.prong == compoActive[parent.forkId - 1]; - } else - return true; - } - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -bool -StateRegistryT>::isResumable(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - if (Parent parent = stateParents[stateId]) { - HFSM_ASSERT(parent.forkId > 0); - - return parent.prong == resumable[parent.forkId - 1]; - } - - return false; -} - -//------------------------------------------------------------------------------ - -template -bool -StateRegistryT>::isPendingChange(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - if (Parent parent = stateParents[stateId]) { - HFSM_ASSERT(parent.forkId > 0); - - return requested.compo[parent.forkId - 1] != - compoActive[parent.forkId - 1]; - } - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -bool -StateRegistryT>::isPendingEnter(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - if (Parent parent = stateParents[stateId]) { - HFSM_ASSERT(parent.forkId > 0); - - return parent.prong != compoActive[parent.forkId - 1] && - parent.prong == requested.compo[parent.forkId - 1]; - } - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -bool -StateRegistryT>::isPendingExit(const StateID stateId) const { - if (HFSM_CHECKED(stateId < STATE_COUNT)) - if (Parent parent = stateParents[stateId]) { - HFSM_ASSERT(parent.forkId > 0); - - return parent.prong == compoActive[parent.forkId - 1] && - parent.prong != requested.compo[parent.forkId - 1]; - } - - return false; -} - -//------------------------------------------------------------------------------ - -template -const Parent& -StateRegistryT>::forkParent(const ForkID forkId) const { - HFSM_ASSERT(forkId > 0); - - return compoParents[forkId - 1]; -} - -//------------------------------------------------------------------------------ - -template -bool -StateRegistryT>::requestImmediate(const Request request) { - if (request.stateId == 0) - return false; - else if (HFSM_CHECKED(request.stateId < STATE_COUNT)) { - Parent parent = stateParents[request.stateId]; - - if (HFSM_CHECKED(parent)) { - HFSM_ASSERT(parent.forkId > 0); - - requested.compo[parent.forkId - 1] = parent.prong; - - for (parent = forkParent(parent.forkId); - parent; - parent = forkParent(parent.forkId)) - { - HFSM_ASSERT(parent.forkId > 0); - compoRemains.set(parent.forkId - 1); - - if ( compoActive[parent.forkId - 1] != parent.prong) - requested.compo[parent.forkId - 1] = parent.prong; - else { - parent = forkParent(parent.forkId); - break; - } - } - - for (; parent; parent = forkParent(parent.forkId)) { - HFSM_ASSERT(parent.forkId > 0); - compoRemains.set(parent.forkId - 1); - } - } - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template -void -StateRegistryT>::requestScheduled(const StateID stateId) { - HFSM_ASSERT(stateId < STATE_COUNT); - - if (stateId < STATE_COUNT) { - const Parent parent = stateParents[stateId]; - - if (HFSM_CHECKED(parent.forkId > 0)) - resumable[parent.forkId - 1] = parent.prong; - } -} - -//------------------------------------------------------------------------------ - -template -void -StateRegistryT>::clearRequests() { - compoRemains.clear(); - requested.clear(); -} - -//////////////////////////////////////////////////////////////////////////////// - -} -} diff --git a/include/hfsm2/detail/shared/array.hpp b/include/hfsm2/detail/shared/array.hpp index d174f92..061abed 100644 --- a/include/hfsm2/detail/shared/array.hpp +++ b/include/hfsm2/detail/shared/array.hpp @@ -12,7 +12,7 @@ class StaticArray { static constexpr LongIndex DUMMY = INVALID_LONG_INDEX; using Item = T; - using Index = Unsigned; + using Index = UnsignedCapacity; public: HFSM_INLINE StaticArray() = default; @@ -24,6 +24,7 @@ class StaticArray { HFSM_INLINE LongIndex count() const { return CAPACITY; } HFSM_INLINE void fill(const Item filler); + HFSM_INLINE void clear() { fill(INVALID_SHORT_INDEX); } HFSM_INLINE Iterator< StaticArray> begin() { return Iterator< StaticArray>(*this, 0); } HFSM_INLINE Iterator begin() const { return Iterator(*this, 0); } diff --git a/include/hfsm2/detail/shared/bit_array.inl b/include/hfsm2/detail/shared/bit_array.inl index c5cbe16..18175aa 100644 --- a/include/hfsm2/detail/shared/bit_array.inl +++ b/include/hfsm2/detail/shared/bit_array.inl @@ -7,6 +7,7 @@ template BitArray::Bits::operator bool() const { const ShortIndex fullUnits = _width / (sizeof(Unit) * 8); + // TODO: cover this case for (Index i = 0; i < fullUnits; ++i) if (_storage[i]) return true; diff --git a/include/hfsm2/detail/shared/bit_stream.hpp b/include/hfsm2/detail/shared/bit_stream.hpp new file mode 100644 index 0000000..d93c954 --- /dev/null +++ b/include/hfsm2/detail/shared/bit_stream.hpp @@ -0,0 +1,73 @@ +#pragma once + +namespace hfsm2 { +namespace detail { + +//------------------------------------------------------------------------------ + +template +struct StreamBuffer { + static constexpr LongIndex BIT_CAPACITY = NBitCapacity; + static constexpr LongIndex BYTE_COUNT = roundUp(BIT_CAPACITY, 8); + + using Size = UnsignedCapacity; + using Data = uint8_t[BYTE_COUNT]; + + void clear(); + + //Size write(const uint8_t byte); + + Size bitSize; + Data payload; +}; + +//////////////////////////////////////////////////////////////////////////////// + +template +class BitWriteStream final { +public: + static constexpr LongIndex BIT_CAPACITY = NBitCapacity; + + using Buffer = StreamBuffer; + +public: + BitWriteStream(Buffer& _buffer); + + template + void write(const UnsignedBitWidth item); + +private: + Buffer& _buffer; +}; + +//------------------------------------------------------------------------------ + +template +class BitReadStream final { +public: + static constexpr LongIndex BIT_CAPACITY = NBitCapacity; + + using Buffer = StreamBuffer; + +public: + BitReadStream(const Buffer& buffer) + : _buffer{buffer} + {} + + template + UnsignedBitWidth read(); + + LongIndex cursor() const { return _cursor; } + +private: + const Buffer& _buffer; + + LongIndex _cursor = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// + +} +} + +#include "bit_stream.inl" diff --git a/include/hfsm2/detail/shared/bit_stream.inl b/include/hfsm2/detail/shared/bit_stream.inl new file mode 100644 index 0000000..afac494 --- /dev/null +++ b/include/hfsm2/detail/shared/bit_stream.inl @@ -0,0 +1,94 @@ +#pragma once + +namespace hfsm2 { +namespace detail { + +//////////////////////////////////////////////////////////////////////////////// + +template +void +StreamBuffer::clear() { + bitSize = 0; + fill(payload, 0); +} + +//////////////////////////////////////////////////////////////////////////////// + +template +BitWriteStream::BitWriteStream(Buffer& buffer) + : _buffer{buffer} +{ + _buffer.clear(); +} + +//------------------------------------------------------------------------------ + +template +template +void +BitWriteStream::write(const UnsignedBitWidth item) { + constexpr ShortIndex BIT_WIDTH = NBitWidth; + static_assert(BIT_WIDTH > 0, "STATIC ASSERT"); + + HFSM_ASSERT(_buffer.bitSize + BIT_WIDTH < BIT_CAPACITY); + + using Item = UnsignedBitWidth; + + Item itemBits = item; + + for (ShortIndex itemWidth = BIT_WIDTH; itemWidth; ) { + const LongIndex byteIndex = _buffer.bitSize >> 3; + uint8_t& byte = _buffer.payload[byteIndex]; + + const ShortIndex byteChunkStart = _buffer.bitSize & 0x7; + const ShortIndex byteDataWidth = 8 - byteChunkStart; + const ShortIndex byteChunkWidth = detail::min(byteDataWidth, itemWidth); + const Item byteChunk = itemBits << byteChunkStart; + byte |= byteChunk; + + itemBits >>= byteChunkWidth; + itemWidth -= byteChunkWidth; + _buffer.bitSize += byteChunkWidth; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +template +template +UnsignedBitWidth +BitReadStream::read() { + constexpr ShortIndex BIT_WIDTH = NBitWidth; + static_assert(BIT_WIDTH > 0, "STATIC ASSERT"); + + using Item = UnsignedBitWidth; + + Item item = 0; + ShortIndex itemCursor = 0; + + for (ShortIndex itemWidth = BIT_WIDTH; itemWidth; ) + if (HFSM_CHECKED(_cursor + itemWidth <= _buffer.bitSize)) { + const LongIndex byteIndex = _cursor >> 3; + const uint8_t& byte = _buffer.payload[byteIndex]; + + const ShortIndex byteChunkStart = _cursor & 0x7; + const ShortIndex byteDataWidth = 8 - byteChunkStart; + const ShortIndex byteChunkWidth = detail::min(byteDataWidth, itemWidth); + const ShortIndex byteChunkMask = (1 << byteChunkWidth) - 1; + const Item byteChunk = (byte >> byteChunkStart) & byteChunkMask; + + const Item itemChunk = byteChunk << itemCursor; + item |= itemChunk; + + _cursor += byteChunkWidth; + itemCursor += byteChunkWidth; + itemWidth -= byteChunkWidth; + } + + return item; +} + +//////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/include/hfsm2/detail/shared/random.inl b/include/hfsm2/detail/shared/random.inl index 0b5ee89..d52f68d 100644 --- a/include/hfsm2/detail/shared/random.inl +++ b/include/hfsm2/detail/shared/random.inl @@ -4,23 +4,6 @@ namespace hfsm2 { namespace detail { -template -TO convert(const TI& in) { - static_assert(sizeof(TI) == sizeof(TO), ""); - - TO out; - -#if defined(__GNUC__) || defined(__GNUG__) - memcpy (&out, &in, sizeof(in)); -#else - memcpy_s(&out, sizeof(out), &in, sizeof(in)); -#endif - - return out; -} - -//------------------------------------------------------------------------------ - inline float uniformReal(const uint32_t uint) { diff --git a/include/hfsm2/detail/shared/utility.hpp b/include/hfsm2/detail/shared/utility.hpp index 5d78d6e..700107a 100644 --- a/include/hfsm2/detail/shared/utility.hpp +++ b/include/hfsm2/detail/shared/utility.hpp @@ -124,6 +124,14 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#ifdef HFSM_ENABLE_SERIALIZATION + #define HFSM_IF_SERIALIZATION(...) __VA_ARGS__ +#else + #define HFSM_IF_SERIALIZATION(...) +#endif + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + #if defined _MSC_VER || defined __clang_major__ && __clang_major__ >= 7 #define HFSM_EXPLICIT_MEMBER_SPECIALIZATION #endif @@ -198,7 +206,7 @@ min(const T t1, const T t2) { return t1 < t2 ? t1 : t2; } //------------------------------------------------------------------------------ template -struct UnsignedT { +struct UnsignedCapacityT { static constexpr LongIndex CAPACITY = NCapacity; using Type = typename std::conditional -using Unsigned = typename UnsignedT::Type; +using UnsignedCapacity = typename UnsignedCapacityT::Type; + +//------------------------------------------------------------------------------ + +template +struct UnsignedBitWidthT { + static constexpr ShortIndex BIT_WIDTH = NBitWidth; + + using Type = typename std::conditional::type>::type>::type; + + static_assert(BIT_WIDTH <= 64, "STATIC ASSERT"); +}; + +template +using UnsignedBitWidth = typename UnsignedBitWidthT::Type; //------------------------------------------------------------------------------ @@ -227,14 +252,39 @@ roundUp(const LongIndex x, constexpr ShortIndex bitWidth(const ShortIndex x) { - return x < 2 ? 1 : - x < 4 ? 2 : - x < 8 ? 3 : - x < 16 ? 4 : - x < 32 ? 5 : - x < 64 ? 6 : - x < 128 ? 7 : - 8 ; + return x <= 2 ? 1 : + x <= 4 ? 2 : + x <= 8 ? 3 : + x <= 16 ? 4 : + x <= 32 ? 5 : + x <= 64 ? 6 : + x <= 128 ? 7 : + 8 ; +} + +//------------------------------------------------------------------------------ + +template +void +overwrite(TTo& to, const TFrom& from) { + static_assert(sizeof(TTo) == sizeof(TFrom), "STATIC ASSERT"); + +#if defined(__GNUC__) || defined(__GNUG__) + memcpy (&to, &from, sizeof(from)); +#else + memcpy_s(&to, sizeof(to), &from, sizeof(from)); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +TO convert(const TI& in) { + TO out; + + overwrite(out, in); + + return out; } //////////////////////////////////////////////////////////////////////////////// diff --git a/include/hfsm2/detail/structure/composite.hpp b/include/hfsm2/detail/structure/composite.hpp index f0c8f79..66d9bcb 100644 --- a/include/hfsm2/detail/structure/composite.hpp +++ b/include/hfsm2/detail/structure/composite.hpp @@ -27,8 +27,8 @@ struct C_ final { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using Control = ControlT; @@ -56,53 +56,59 @@ struct C_ final { TSubStates...>; using Info = CI_; - static constexpr ShortIndex REGION_SIZE = Info::STATE_COUNT; + static constexpr ShortIndex WIDTH = Info::WIDTH; + static constexpr ShortIndex WIDTH_BITS = Info::WIDTH_BITS; + static constexpr ShortIndex STATE_COUNT = Info::STATE_COUNT; //---------------------------------------------------------------------- #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template struct Accessor { - HFSM_INLINE static T& get( C_& c) { return c._subStates.template access(); } - HFSM_INLINE static const T& get(const C_& c) { return c._subStates.template access(); } + HFSM_INLINE static T& get( C_& c) { return c._subStates.template access(); } + HFSM_INLINE static const T& get(const C_& c) { return c._subStates.template access(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template <> struct Accessor { - HFSM_INLINE static Head& get( C_& c) { return c._headState._headBox.get(); } - HFSM_INLINE static const Head& get(const C_& c) { return c._headState._headBox.get(); } + HFSM_INLINE static Head& get( C_& c) { return c._headState._headBox.get(); } + HFSM_INLINE static const Head& get(const C_& c) { return c._headState._headBox.get(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - HFSM_INLINE T& access() { return Accessor::get(*this); } + HFSM_INLINE T& access() { return Accessor::get(*this); } template - HFSM_INLINE const T& access() const { return Accessor::get(*this); } - + HFSM_INLINE const T& access() const { return Accessor::get(*this); } #endif //---------------------------------------------------------------------- - HFSM_INLINE ShortIndex& compoActive (StateRegistry& stateRegistry) { return stateRegistry.compoActive [COMPO_INDEX]; } - HFSM_INLINE ShortIndex& compoResumable(StateRegistry& stateRegistry) { return stateRegistry.resumable [COMPO_INDEX]; } - HFSM_INLINE ShortIndex& compoRequested(StateRegistry& stateRegistry) { return stateRegistry.requested.compo[COMPO_INDEX]; } + HFSM_INLINE ShortIndex& compoRequested( Registry& registry) const { return registry.compoRequested[COMPO_INDEX]; } + HFSM_INLINE const ShortIndex& compoRequested(const Registry& registry) const { return registry.compoRequested[COMPO_INDEX]; } + + HFSM_INLINE ShortIndex& compoActive ( Registry& registry) const { return registry.compoActive [COMPO_INDEX]; } + HFSM_INLINE const ShortIndex& compoActive (const Registry& registry) const { return registry.compoActive [COMPO_INDEX]; } + + HFSM_INLINE ShortIndex& compoResumable( Registry& registry) const { return registry.compoResumable[COMPO_INDEX]; } + HFSM_INLINE const ShortIndex& compoResumable(const Registry& registry) const { return registry.compoResumable[COMPO_INDEX]; } + + HFSM_INLINE ShortIndex& compoRequested( Control& control) const { return compoRequested(control._registry); } + HFSM_INLINE const ShortIndex& compoRequested(const Control& control) const { return compoRequested(control._registry); } + + HFSM_INLINE ShortIndex& compoActive ( Control& control) const { return compoActive (control._registry); } + HFSM_INLINE const ShortIndex& compoActive (const Control& control) const { return compoActive (control._registry); } - HFSM_INLINE ShortIndex& compoActive (Control& control) { return compoActive (control._stateRegistry); } - HFSM_INLINE ShortIndex& compoResumable(Control& control) { return compoResumable(control._stateRegistry); } - HFSM_INLINE ShortIndex& compoRequested(Control& control) { return compoRequested(control._stateRegistry); } + HFSM_INLINE ShortIndex& compoResumable( Control& control) const { return compoResumable(control._registry); } + HFSM_INLINE const ShortIndex& compoResumable(const Control& control) const { return compoResumable(control._registry); } - HFSM_INLINE ShortIndex resolveRandom (Control& control, - const Utility(& options)[Info::WIDTH], const Utility sum, - const Rank (& ranks) [Info::WIDTH], const Rank top); + HFSM_INLINE ShortIndex resolveRandom (Control& control, + const Utility(& options)[Info::WIDTH], const Utility sum, + const Rank (& ranks) [Info::WIDTH], const Rank top) const; - HFSM_INLINE bool compoRemain (Control& control) { return control._stateRegistry.compoRemains.template get(); } + HFSM_INLINE bool compoRemain (Control& control) { return control._registry.compoRemains.template get(); } - HFSM_INLINE void deepRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void deepRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -165,9 +171,9 @@ struct C_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void deepRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void deepRequestRemain (Registry& registry); + HFSM_INLINE void deepRequestRestart (Registry& registry); + HFSM_INLINE void deepRequestResume (Registry& registry); HFSM_INLINE void deepRequestUtilize (Control& control); HFSM_INLINE void deepRequestRandomize (Control& control); @@ -211,6 +217,8 @@ struct C_ final { HFSM_INLINE void deepChangeToRequested (PlanControl& control); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -223,6 +231,21 @@ struct C_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void deepSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void deepSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void deepLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void deepLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + HeadState _headState; SubStates _subStates; diff --git a/include/hfsm2/detail/structure/composite.inl b/include/hfsm2/detail/structure/composite.inl index c736732..296b0c5 100644 --- a/include/hfsm2/detail/structure/composite.inl +++ b/include/hfsm2/detail/structure/composite.inl @@ -9,7 +9,7 @@ C_::resolveRandom(Control& control, const Utility(& options)[Info::WIDTH], const Utility sum, const Rank(& ranks)[Info::WIDTH], - const Rank top) + const Rank top) const { const Utility random = control._rng.next(); HFSM_ASSERT(0.0f <= random && random < 1.0f); @@ -37,13 +37,13 @@ C_::resolveRandom(Control& control, template void -C_::deepRegister(StateRegistry& stateRegistry, +C_::deepRegister(Registry& registry, const Parent parent) { - stateRegistry.compoParents[COMPO_INDEX] = parent; + registry.compoParents[COMPO_INDEX] = parent; - _headState.deepRegister(stateRegistry, parent); - _subStates.wideRegister(stateRegistry, Parent{COMPO_ID}); + _headState.deepRegister(registry, parent); + _subStates.wideRegister(registry, Parent{COMPO_ID}); } //------------------------------------------------------------------------------ @@ -56,7 +56,7 @@ C_::deepForwardEntryGuard(GuardControl& control) { HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (requested == INVALID_SHORT_INDEX) return _subStates.wideForwardEntryGuard(control, active); @@ -72,7 +72,7 @@ C_::deepEntryGuard(GuardControl& control) { const ShortIndex requested = compoRequested(control); HFSM_ASSERT(requested != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; return _headState.deepEntryGuard(control) || _subStates.wideEntryGuard(control, requested); @@ -108,7 +108,7 @@ void C_::deepEnter(PlanControl& control) { const ShortIndex& active = compoActive(control); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; _headState.deepEnter(control); _subStates.wideEnter(control, active); @@ -126,7 +126,7 @@ C_::deepReenter(PlanControl& control) { HFSM_ASSERT(active != INVALID_SHORT_INDEX && requested != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; _headState.deepReenter(control); @@ -154,7 +154,7 @@ C_::deepUpdate(FullControl& control) { const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion outer{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion outer{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (const Status headStatus = _headState.deepUpdate(control)) { ControlLock lock{control}; @@ -167,7 +167,7 @@ C_::deepUpdate(FullControl& control) { if (subStatus.outerTransition) return Status{Status::NONE, true}; - ScopedRegion inner{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion inner{control, REGION_ID, HEAD_ID, STATE_COUNT}; return subStatus && control._planData.planExists.template get() ? control.updatePlan(_headState, subStatus) : subStatus; @@ -185,7 +185,7 @@ C_::deepReact(FullControl& control, const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion outer{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion outer{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (const Status headStatus = _headState.deepReact(control, event)) { ControlLock lock{control}; @@ -198,7 +198,7 @@ C_::deepReact(FullControl& control, if (subStatus.outerTransition) return subStatus; - ScopedRegion inner{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion inner{control, REGION_ID, HEAD_ID, STATE_COUNT}; return subStatus && control._planData.planExists.template get() ? control.updatePlan(_headState, subStatus) : subStatus; @@ -213,7 +213,7 @@ C_::deepForwardExitGuard(GuardControl& control) { const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (compoRequested(control) == INVALID_SHORT_INDEX) return _subStates.wideForwardExitGuard(control, active); @@ -229,7 +229,7 @@ C_::deepExitGuard(GuardControl& control) { const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; return _headState.deepExitGuard(control) || _subStates.wideExitGuard(control, active); @@ -274,7 +274,7 @@ void C_::deepForwardActive(Control& control, const Request::Type request) { - HFSM_ASSERT(control._stateRegistry.isActive(HEAD_ID)); + HFSM_ASSERT(control._registry.isActive(HEAD_ID)); const ShortIndex requested = compoRequested(control); @@ -310,7 +310,7 @@ C_::deepRequest(Control& control, { switch (request) { case Request::REMAIN: - deepRequestRemain (control._stateRegistry); + deepRequestRemain (control._registry); break; case Request::CHANGE: @@ -318,11 +318,11 @@ C_::deepRequest(Control& control, break; case Request::RESTART: - deepRequestRestart (control._stateRegistry); + deepRequestRestart (control._registry); break; case Request::RESUME: - deepRequestResume (control._stateRegistry); + deepRequestResume (control._registry); break; case Request::UTILIZE: @@ -430,40 +430,40 @@ C_::deepRequestChangeRandom(Control& control) { template void -C_::deepRequestRemain(StateRegistry& stateRegistry) { - const ShortIndex active = compoActive (stateRegistry); - ShortIndex& requested = compoRequested(stateRegistry); +C_::deepRequestRemain(Registry& registry) { + const ShortIndex active = compoActive (registry); + ShortIndex& requested = compoRequested(registry); if (active == INVALID_SHORT_INDEX) requested = 0; - _subStates.wideRequestRemain(stateRegistry); + _subStates.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -C_::deepRequestRestart(StateRegistry& stateRegistry) { - ShortIndex& requested = compoRequested(stateRegistry); +C_::deepRequestRestart(Registry& registry) { + ShortIndex& requested = compoRequested(registry); requested = 0; - _subStates.wideRequestRestart(stateRegistry); + _subStates.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -C_::deepRequestResume(StateRegistry& stateRegistry) { - const ShortIndex resumable = compoResumable(stateRegistry); - ShortIndex& requested = compoRequested(stateRegistry); +C_::deepRequestResume(Registry& registry) { + const ShortIndex resumable = compoResumable(registry); + ShortIndex& requested = compoRequested(registry); requested = (resumable != INVALID_SHORT_INDEX) ? resumable : 0; - _subStates.wideRequestResume(stateRegistry, requested); + _subStates.wideRequestResume(registry, requested); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -706,6 +706,89 @@ C_::deepGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +C_::deepSaveActive(const Registry& registry, + WriteStream& stream) const +{ + const ShortIndex active = compoActive (registry); + const ShortIndex resumable = compoResumable(registry); + + stream.template write(active); + + if (resumable != INVALID_SHORT_INDEX) { + stream.template write<1>(1); + stream.template write(resumable); + } else + stream.template write<1>(0); + + _subStates.wideSaveActive(registry,stream, active); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +C_::deepSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + const ShortIndex resumable = compoResumable(registry); + + if (resumable != INVALID_SHORT_INDEX) { + stream.template write<1>(1); + stream.template write(resumable); + } else + stream.template write<1>(0); + + _subStates.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +C_::deepLoadRequested(Registry& registry, + ReadStream& stream) const +{ + ShortIndex& resumable = compoResumable(registry); + ShortIndex& requested = compoRequested(registry); + + requested = stream.template read(); + HFSM_ASSERT(requested < WIDTH); + + if (stream.template read<1>()) { + resumable = stream.template read(); + HFSM_ASSERT(resumable < WIDTH); + } else + resumable = INVALID_SHORT_INDEX; + + _subStates.wideLoadRequested(registry, stream, requested); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +C_::deepLoadResumable(Registry& registry, + ReadStream& stream) const +{ + ShortIndex& resumable = compoResumable(registry); + + if (stream.template read<1>()) { + resumable = stream.template read(); + HFSM_ASSERT(resumable < WIDTH); + } else + resumable = INVALID_SHORT_INDEX; + + _subStates.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } diff --git a/include/hfsm2/detail/structure/composite_sub.hpp b/include/hfsm2/detail/structure/composite_sub.hpp index bc4b070..96bec70 100644 --- a/include/hfsm2/detail/structure/composite_sub.hpp +++ b/include/hfsm2/detail/structure/composite_sub.hpp @@ -29,8 +29,8 @@ struct CS_ final { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using Control = ControlT ; using PlanControl = PlanControlT ; @@ -65,18 +65,16 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access(); template HFSM_INLINE const T& access() const; - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void wideRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -129,9 +127,9 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry, const ShortIndex prong); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry, const ShortIndex prong); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -150,6 +148,8 @@ struct CS_ final { HFSM_INLINE void wideChangeToRequested (PlanControl& control, const ShortIndex prong); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -162,11 +162,26 @@ struct CS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream ) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream ) const; +#endif + + //---------------------------------------------------------------------- + LHalf lHalf; RHalf rHalf; }; -//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// template final { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using Control = ControlT ; using PlanControl = PlanControlT ; @@ -210,18 +225,16 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access() { return state.template access(); } template HFSM_INLINE const T& access() const { return state.template access(); } - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void wideRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -257,9 +270,9 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry, const ShortIndex prong); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry, const ShortIndex prong); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -278,6 +291,8 @@ struct CS_ final { HFSM_INLINE void wideChangeToRequested (PlanControl& control, const ShortIndex prong); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -290,6 +305,21 @@ struct CS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream ) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream ) const; +#endif + + //---------------------------------------------------------------------- + State state; }; diff --git a/include/hfsm2/detail/structure/composite_sub_1.inl b/include/hfsm2/detail/structure/composite_sub_1.inl index 9139cc7..7267c7c 100644 --- a/include/hfsm2/detail/structure/composite_sub_1.inl +++ b/include/hfsm2/detail/structure/composite_sub_1.inl @@ -31,11 +31,11 @@ CS_::access() const { template void -CS_::wideRegister(StateRegistry& stateRegistry, +CS_::wideRegister(Registry& registry, const Parent parent) { - lHalf.wideRegister(stateRegistry, Parent{parent.forkId, L_PRONG}); - rHalf.wideRegister(stateRegistry, Parent{parent.forkId, R_PRONG}); + lHalf.wideRegister(registry, Parent{parent.forkId, L_PRONG}); + rHalf.wideRegister(registry, Parent{parent.forkId, R_PRONG}); } //------------------------------------------------------------------------------ @@ -262,31 +262,31 @@ CS_::wideRequestChangeResumable(Control& control, template void -CS_::wideRequestRemain(StateRegistry& stateRegistry) { - lHalf.wideRequestRemain(stateRegistry); +CS_::wideRequestRemain(Registry& registry) { + lHalf.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestRestart(StateRegistry& stateRegistry) { - lHalf.wideRequestRestart(stateRegistry); +CS_::wideRequestRestart(Registry& registry) { + lHalf.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestResume(StateRegistry& stateRegistry, +CS_::wideRequestResume(Registry& registry, const ShortIndex prong) { HFSM_ASSERT(prong != INVALID_SHORT_INDEX); if (prong < R_PRONG) - lHalf.wideRequestResume(stateRegistry, prong); + lHalf.wideRequestResume(registry, prong); else - rHalf.wideRequestResume(stateRegistry, prong); + rHalf.wideRequestResume(registry, prong); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -418,6 +418,70 @@ CS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +CS_::wideSaveActive(const Registry& registry, + WriteStream& stream, + const ShortIndex prong) const +{ + HFSM_ASSERT(prong != INVALID_SHORT_INDEX); + + if (prong < R_PRONG) { + lHalf.wideSaveActive (registry, stream, prong); + rHalf.wideSaveResumable(registry, stream); + } else { + lHalf.wideSaveResumable(registry, stream); + rHalf.wideSaveActive (registry, stream, prong); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + lHalf.wideSaveResumable(registry, stream); + rHalf.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadRequested(Registry& registry, + ReadStream& stream, + const ShortIndex prong) const +{ + HFSM_ASSERT(prong != INVALID_SHORT_INDEX); + + if (prong < R_PRONG) { + lHalf.wideLoadRequested(registry, stream, prong); + rHalf.wideLoadResumable(registry, stream); + } else { + lHalf.wideLoadResumable(registry, stream); + rHalf.wideLoadRequested(registry, stream, prong); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + lHalf.wideLoadResumable(registry, stream); + rHalf.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } diff --git a/include/hfsm2/detail/structure/composite_sub_2.inl b/include/hfsm2/detail/structure/composite_sub_2.inl index 76087c0..c0cf340 100644 --- a/include/hfsm2/detail/structure/composite_sub_2.inl +++ b/include/hfsm2/detail/structure/composite_sub_2.inl @@ -5,10 +5,10 @@ namespace detail { template void -CS_::wideRegister(StateRegistry& stateRegistry, +CS_::wideRegister(Registry& registry, const Parent parent) { - state.deepRegister(stateRegistry, Parent{parent.forkId, PRONG_INDEX}); + state.deepRegister(registry, Parent{parent.forkId, PRONG_INDEX}); } //------------------------------------------------------------------------------ @@ -195,28 +195,28 @@ CS_::wideRequestChangeResumable(Control& control, template void -CS_::wideRequestRemain(StateRegistry& stateRegistry) { - state.deepRequestRemain(stateRegistry); +CS_::wideRequestRemain(Registry& registry) { + state.deepRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestRestart(StateRegistry& stateRegistry) { - state.deepRequestRestart(stateRegistry); +CS_::wideRequestRestart(Registry& registry) { + state.deepRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestResume(StateRegistry& stateRegistry, +CS_::wideRequestResume(Registry& registry, const ShortIndex HFSM_IF_ASSERT(prong)) { HFSM_ASSERT(prong == PRONG_INDEX); - state.deepRequestResume(stateRegistry); + state.deepRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -331,6 +331,56 @@ CS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +CS_::wideSaveActive(const Registry& registry, + WriteStream& stream, + const ShortIndex HFSM_IF_ASSERT(prong)) const +{ + HFSM_ASSERT(prong == PRONG_INDEX); + + state.deepSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + state.deepSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadRequested(Registry& registry, + ReadStream& stream, + const ShortIndex HFSM_IF_ASSERT(prong)) const +{ + HFSM_ASSERT(prong == PRONG_INDEX); + + state.deepLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + state.deepLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } diff --git a/include/hfsm2/detail/structure/forward.hpp b/include/hfsm2/detail/structure/forward.hpp index 5f2569c..4844c65 100644 --- a/include/hfsm2/detail/structure/forward.hpp +++ b/include/hfsm2/detail/structure/forward.hpp @@ -67,15 +67,18 @@ struct SI_ final { using StateList = TL_; using RegionList = TL_<>; - static constexpr ShortIndex WIDTH = 1; - static constexpr LongIndex REVERSE_DEPTH = 1; - static constexpr ShortIndex COMPO_REGIONS = 0; - static constexpr LongIndex COMPO_PRONGS = 0; - static constexpr ShortIndex ORTHO_REGIONS = 0; - static constexpr ShortIndex ORTHO_UNITS = 0; - - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr ShortIndex WIDTH = 1; + static constexpr LongIndex REVERSE_DEPTH = 1; + static constexpr ShortIndex COMPO_REGIONS = 0; + static constexpr LongIndex COMPO_PRONGS = 0; + static constexpr ShortIndex ORTHO_REGIONS = 0; + static constexpr ShortIndex ORTHO_UNITS = 0; + + static constexpr LongIndex ACTIVE_BITS = 0; + static constexpr LongIndex RESUMABLE_BITS = 0; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -87,14 +90,17 @@ struct CSI_ { using StateList = Merge; using RegionList = Merge; - static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = Max::VALUE; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS + Remaining::RESUMABLE_BITS; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; template @@ -103,14 +109,17 @@ struct CSI_ { using StateList = typename Initial::StateList; using RegionList = typename Initial::RegionList; - static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = Initial::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; template @@ -123,15 +132,19 @@ struct CI_ final { using StateList = Merge; using RegionList = Merge; - static constexpr ShortIndex WIDTH = sizeof...(TSubStates); - static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; - static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS + 1; - static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS + WIDTH; - static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS; + static constexpr ShortIndex WIDTH = sizeof...(TSubStates); + static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; + static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS + 1; + static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS + WIDTH; + static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS; + + static constexpr LongIndex WIDTH_BITS = bitWidth(WIDTH); + static constexpr LongIndex ACTIVE_BITS = SubStates::ACTIVE_BITS + WIDTH_BITS; + static constexpr LongIndex RESUMABLE_BITS = SubStates::RESUMABLE_BITS + WIDTH_BITS + 1; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -143,11 +156,14 @@ struct OSI_ { using StateList = Merge; using RegionList = Merge; - static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; + + static constexpr LongIndex ACTIVE_BITS = Initial::ACTIVE_BITS + Remaining::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS + Remaining::RESUMABLE_BITS; }; template @@ -156,11 +172,14 @@ struct OSI_ { using StateList = typename Initial::StateList; using RegionList = typename Initial::RegionList; - static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; + + static constexpr LongIndex ACTIVE_BITS = Initial::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS; }; template @@ -171,15 +190,18 @@ struct OI_ final { using StateList = Merge; using RegionList = Merge; - static constexpr ShortIndex WIDTH = sizeof...(TSubStates); - static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; - static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS + 1; - static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS + (WIDTH + 7) / 8; + static constexpr ShortIndex WIDTH = sizeof...(TSubStates); + static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; + static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS + 1; + static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS + (WIDTH + 7) / 8; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = SubStates::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = SubStates::RESUMABLE_BITS; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; //////////////////////////////////////////////////////////////////////////////// @@ -191,6 +213,7 @@ template struct ArgsT final { using Context = TContext; @@ -209,8 +232,16 @@ struct ArgsT final { static constexpr ShortIndex COMPO_REGIONS = NCompoCount; static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; + static constexpr ShortIndex SERIAL_BITS = NSerialBits; + static constexpr LongIndex TASK_CAPACITY = NTaskCapacity; +#ifdef HFSM_ENABLE_SERIALIZATION + using SerialBuffer = StreamBuffer ; + using WriteStream = BitWriteStream; + using ReadStream = BitReadStream ; +#endif + HFSM_IF_STRUCTURE(using StructureStateInfos = Array); }; @@ -300,6 +331,9 @@ struct RF_ final { static constexpr ShortIndex ORTHO_REGIONS = Apex::ORTHO_REGIONS; static constexpr ShortIndex ORTHO_UNITS = Apex::ORTHO_UNITS; + static constexpr LongIndex ACTIVE_BITS = Apex::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Apex::RESUMABLE_BITS; + using StateList = Indexed; using RegionList = Indexed; @@ -310,6 +344,7 @@ struct RF_ final { COMPO_REGIONS, ORTHO_REGIONS, ORTHO_UNITS, + ACTIVE_BITS + RESUMABLE_BITS, TASK_CAPACITY>; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/include/hfsm2/detail/structure/orthogonal.hpp b/include/hfsm2/detail/structure/orthogonal.hpp index 48a55d2..394a7b2 100644 --- a/include/hfsm2/detail/structure/orthogonal.hpp +++ b/include/hfsm2/detail/structure/orthogonal.hpp @@ -31,9 +31,9 @@ struct O_ final { static constexpr ShortIndex REGION_SIZE = Info::STATE_COUNT; static constexpr ShortIndex ORTHO_UNITS = Info::ORTHO_UNITS; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; - using OrthoForks = typename StateRegistry::AllForks::Ortho; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; + using OrthoForks = typename Registry::OrthoForks; using ProngBits = typename OrthoForks::Bits; using ProngConstBits= typename OrthoForks::ConstBits; @@ -61,40 +61,34 @@ struct O_ final { //---------------------------------------------------------------------- #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template struct Accessor { - HFSM_INLINE static T& get( O_& o) { return o._subStates.template access(); } - HFSM_INLINE static const T& get(const O_& o) { return o._subStates.template access(); } + HFSM_INLINE static T& get( O_& o) { return o._subStates.template access(); } + HFSM_INLINE static const T& get(const O_& o) { return o._subStates.template access(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template <> struct Accessor { - HFSM_INLINE static Head& get( O_& o) { return o._headState._headBox.get(); } - HFSM_INLINE static const Head& get(const O_& o) { return o._headState._headBox.get(); } + HFSM_INLINE static Head& get( O_& o) { return o._headState._headBox.get(); } + HFSM_INLINE static const Head& get(const O_& o) { return o._headState._headBox.get(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - HFSM_INLINE T& access() { return Accessor::get(*this); } + HFSM_INLINE T& access() { return Accessor::get(*this); } template - HFSM_INLINE const T& access() const { return Accessor::get(*this); } - + HFSM_INLINE const T& access() const { return Accessor::get(*this); } #endif //---------------------------------------------------------------------- - HFSM_INLINE ProngBits orthoRequested( StateRegistry& stateRegistry) { return stateRegistry.requested.ortho.template bits(); } - HFSM_INLINE ProngConstBits orthoRequested(const StateRegistry& stateRegistry) const { return stateRegistry.requested.ortho.template bits(); } + HFSM_INLINE ProngBits orthoRequested( Registry& registry) { return registry.orthoRequested.template bits(); } + HFSM_INLINE ProngConstBits orthoRequested(const Registry& registry) const { return registry.orthoRequested.template bits(); } - HFSM_INLINE ProngBits orthoRequested( Control& control) { return orthoRequested(control._stateRegistry); } - HFSM_INLINE ProngConstBits orthoRequested(const Control& control) const { return orthoRequested(control._stateRegistry); } + HFSM_INLINE ProngBits orthoRequested( Control& control) { return orthoRequested(control._registry); } + HFSM_INLINE ProngConstBits orthoRequested(const Control& control) const { return orthoRequested(control._registry); } - HFSM_INLINE void deepRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void deepRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -128,9 +122,9 @@ struct O_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void deepRequestChange (Control& control); - HFSM_INLINE void deepRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void deepRequestRemain (Registry& registry); + HFSM_INLINE void deepRequestRestart (Registry& registry); + HFSM_INLINE void deepRequestResume (Registry& registry); HFSM_INLINE void deepRequestUtilize (Control& control); HFSM_INLINE void deepRequestRandomize (Control& control); @@ -143,7 +137,7 @@ struct O_ final { HFSM_INLINE void deepChangeToRequested(PlanControl& control); - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + //---------------------------------------------------------------------- #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; @@ -157,6 +151,21 @@ struct O_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void deepSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void deepSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void deepLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void deepLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + HeadState _headState; SubStates _subStates; }; diff --git a/include/hfsm2/detail/structure/orthogonal.inl b/include/hfsm2/detail/structure/orthogonal.inl index 0a74bff..d635221 100644 --- a/include/hfsm2/detail/structure/orthogonal.inl +++ b/include/hfsm2/detail/structure/orthogonal.inl @@ -5,14 +5,14 @@ namespace detail { template void -O_::deepRegister(StateRegistry& stateRegistry, +O_::deepRegister(Registry& registry, const Parent parent) { - stateRegistry.orthoParents[ORTHO_INDEX] = parent; - stateRegistry.orthoUnits[ORTHO_INDEX] = Units{ORTHO_UNIT, WIDTH}; + registry.orthoParents[ORTHO_INDEX] = parent; + registry.orthoUnits[ORTHO_INDEX] = Units{ORTHO_UNIT, WIDTH}; - _headState.deepRegister(stateRegistry, parent); - _subStates.wideRegister(stateRegistry, ORTHO_ID); + _headState.deepRegister(registry, parent); + _subStates.wideRegister(registry, ORTHO_ID); } //------------------------------------------------------------------------------ @@ -182,7 +182,7 @@ void O_::deepForwardActive(Control& control, const Request::Type request) { - HFSM_ASSERT(control._stateRegistry.isActive(HEAD_ID)); + HFSM_ASSERT(control._registry.isActive(HEAD_ID)); const ProngConstBits requested = orthoRequested(static_cast(control)); HFSM_ASSERT(!!requested); @@ -214,7 +214,7 @@ O_::deepRequest(Control& control, { switch (request) { case Request::REMAIN: - deepRequestRemain (control._stateRegistry); + deepRequestRemain (control._registry); break; case Request::CHANGE: @@ -222,11 +222,11 @@ O_::deepRequest(Control& control, break; case Request::RESTART: - deepRequestRestart(control._stateRegistry); + deepRequestRestart(control._registry); break; case Request::RESUME: - deepRequestResume (control._stateRegistry); + deepRequestResume (control._registry); break; case Request::UTILIZE: @@ -254,24 +254,24 @@ O_::deepRequestChange(Control& control) { template void -O_::deepRequestRemain(StateRegistry& stateRegistry) { - _subStates.wideRequestRemain(stateRegistry); +O_::deepRequestRemain(Registry& registry) { + _subStates.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -O_::deepRequestRestart(StateRegistry& stateRegistry) { - _subStates.wideRequestRestart(stateRegistry); +O_::deepRequestRestart(Registry& registry) { + _subStates.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -O_::deepRequestResume(StateRegistry& stateRegistry) { - _subStates.wideRequestResume(stateRegistry); +O_::deepRequestResume(Registry& registry) { + _subStates.wideRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -374,6 +374,50 @@ O_::deepGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +O_::deepSaveActive(const Registry& registry, + WriteStream& stream) const +{ + _subStates.wideSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +O_::deepSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + _subStates.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +O_::deepLoadRequested(Registry& registry, + ReadStream& stream) const +{ + _subStates.wideLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +O_::deepLoadResumable(Registry& registry, + ReadStream& stream) const +{ + _subStates.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } diff --git a/include/hfsm2/detail/structure/orthogonal_sub.hpp b/include/hfsm2/detail/structure/orthogonal_sub.hpp index fb568e5..e4b2e0b 100644 --- a/include/hfsm2/detail/structure/orthogonal_sub.hpp +++ b/include/hfsm2/detail/structure/orthogonal_sub.hpp @@ -27,9 +27,9 @@ struct OS_ final { using Utility = typename Args::Utility; using UP = typename Args::UP; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; - using OrthoForks = typename StateRegistry::AllForks::Ortho; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; + using OrthoForks = typename Registry::OrthoForks; using ProngBits = typename OrthoForks::Bits; using ProngConstBits= typename OrthoForks::ConstBits; @@ -61,18 +61,16 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access(); template HFSM_INLINE const T& access() const; - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const ForkID forkId); + HFSM_INLINE void wideRegister (Registry& registry, const ForkID forkId); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -106,9 +104,9 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestChange (Control& control); - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry); HFSM_INLINE void wideRequestUtilize (Control& control); HFSM_INLINE void wideRequestRandomize (Control& control); @@ -120,6 +118,8 @@ struct OS_ final { HFSM_INLINE void wideChangeToRequested(PlanControl& control); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; @@ -130,11 +130,26 @@ struct OS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + Initial initial; Remaining remaining; }; -//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// template final { using Utility = typename Args::Utility; using UP = typename Args::UP; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; - using OrthoForks = typename StateRegistry::AllForks::Ortho; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; + using OrthoForks = typename Registry::OrthoForks; using ProngBits = typename OrthoForks::Bits; using ProngConstBits= typename OrthoForks::ConstBits; @@ -177,18 +192,16 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access() { return initial.template access(); } template HFSM_INLINE const T& access() const { return initial.template access(); } - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const ForkID forkId); + HFSM_INLINE void wideRegister (Registry& registry, const ForkID forkId); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -222,9 +235,9 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestChange (Control& control); - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry); HFSM_INLINE void wideRequestUtilize (Control& control); HFSM_INLINE void wideRequestRandomize (Control& control); @@ -236,6 +249,8 @@ struct OS_ final { HFSM_INLINE void wideChangeToRequested(PlanControl& control); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; @@ -246,6 +261,21 @@ struct OS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + Initial initial; }; diff --git a/include/hfsm2/detail/structure/orthogonal_sub_1.inl b/include/hfsm2/detail/structure/orthogonal_sub_1.inl index 61ebf4c..984a49a 100644 --- a/include/hfsm2/detail/structure/orthogonal_sub_1.inl +++ b/include/hfsm2/detail/structure/orthogonal_sub_1.inl @@ -31,11 +31,11 @@ OS_::access() const { template void -OS_::wideRegister(StateRegistry& stateRegistry, +OS_::wideRegister(Registry& registry, const ForkID forkId) { - initial .deepRegister(stateRegistry, Parent{forkId, PRONG_INDEX}); - remaining.wideRegister(stateRegistry, forkId); + initial .deepRegister(registry, Parent{forkId, PRONG_INDEX}); + remaining.wideRegister(registry, forkId); } //------------------------------------------------------------------------------ @@ -221,27 +221,27 @@ OS_::wideRequestChange(Control& control) { template void -OS_::wideRequestRemain(StateRegistry& stateRegistry) { - initial .deepRequestRemain(stateRegistry); - remaining.wideRequestRemain(stateRegistry); +OS_::wideRequestRemain(Registry& registry) { + initial .deepRequestRemain(registry); + remaining.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestRestart(StateRegistry& stateRegistry) { - initial .deepRequestRestart(stateRegistry); - remaining.wideRequestRestart(stateRegistry); +OS_::wideRequestRestart(Registry& registry) { + initial .deepRequestRestart(registry); + remaining.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestResume(StateRegistry& stateRegistry) { - initial .deepRequestResume(stateRegistry); - remaining.wideRequestResume(stateRegistry); +OS_::wideRequestResume(Registry& registry) { + initial .deepRequestResume(registry); + remaining.wideRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -320,6 +320,54 @@ OS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +OS_::wideSaveActive(const Registry& registry, + WriteStream& stream) const +{ + initial .deepSaveActive(registry, stream); + remaining.wideSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + initial .deepSaveResumable(registry, stream); + remaining.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadRequested(Registry& registry, + ReadStream& stream) const +{ + initial .deepLoadRequested(registry, stream); + remaining.wideLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + initial .deepLoadResumable(registry, stream); + remaining.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } diff --git a/include/hfsm2/detail/structure/orthogonal_sub_2.inl b/include/hfsm2/detail/structure/orthogonal_sub_2.inl index e36f45d..0390bcf 100644 --- a/include/hfsm2/detail/structure/orthogonal_sub_2.inl +++ b/include/hfsm2/detail/structure/orthogonal_sub_2.inl @@ -5,10 +5,10 @@ namespace detail { template void -OS_::wideRegister(StateRegistry& stateRegistry, +OS_::wideRegister(Registry& registry, const ForkID forkId) { - initial.deepRegister(stateRegistry, Parent{forkId, PRONG_INDEX}); + initial.deepRegister(registry, Parent{forkId, PRONG_INDEX}); } //------------------------------------------------------------------------------ @@ -164,24 +164,24 @@ OS_::wideRequestChange(Control& control) { template void -OS_::wideRequestRemain(StateRegistry& stateRegistry) { - initial.deepRequestRemain(stateRegistry); +OS_::wideRequestRemain(Registry& registry) { + initial.deepRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestRestart(StateRegistry& stateRegistry) { - initial.deepRequestRestart(stateRegistry); +OS_::wideRequestRestart(Registry& registry) { + initial.deepRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestResume(StateRegistry& stateRegistry) { - initial.deepRequestResume(stateRegistry); +OS_::wideRequestResume(Registry& registry) { + initial.deepRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -253,6 +253,50 @@ OS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +OS_::wideSaveActive(const Registry& registry, + WriteStream& stream) const +{ + initial.deepSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + initial.deepSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadRequested(Registry& registry, + ReadStream& stream) const +{ + initial.deepLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + initial.deepLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } diff --git a/include/hfsm2/detail/structure/state.hpp b/include/hfsm2/detail/structure/state.hpp index 7cd4087..b3cf801 100644 --- a/include/hfsm2/detail/structure/state.hpp +++ b/include/hfsm2/detail/structure/state.hpp @@ -16,8 +16,8 @@ struct S_ final { using Logger = typename TArgs::Logger; using Control = ControlT; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using PlanControl = PlanControlT; using ScopedOrigin = typename PlanControl::Origin; @@ -31,7 +31,6 @@ struct S_ final { //---------------------------------------------------------------------- #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnull-dereference" @@ -47,29 +46,24 @@ struct S_ final { #pragma clang diagnostic pop #endif - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template <> struct Accessor { HFSM_INLINE static Head& get( S_& s) { return s._headBox.get(); } HFSM_INLINE static const Head& get(const S_& s) { return s._headBox.get(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template HFSM_INLINE T& access() { return Accessor::get(*this); } template HFSM_INLINE const T& access() const { return Accessor::get(*this); } - #endif //---------------------------------------------------------------------- - HFSM_INLINE Parent stateParent (Control& control) { return control._stateRegistry.stateParents[STATE_ID]; } + HFSM_INLINE Parent stateParent (Control& control) { return control._registry.stateParents[STATE_ID]; } - HFSM_INLINE void deepRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void deepRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -108,9 +102,9 @@ struct S_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void deepRequestChange (Control&) {} - HFSM_INLINE void deepRequestRemain (StateRegistry&) {} - HFSM_INLINE void deepRequestRestart (StateRegistry&) {} - HFSM_INLINE void deepRequestResume (StateRegistry&) {} + HFSM_INLINE void deepRequestRemain (Registry&) {} + HFSM_INLINE void deepRequestRestart (Registry&) {} + HFSM_INLINE void deepRequestResume (Registry&) {} HFSM_INLINE void deepRequestUtilize (Control&) {} HFSM_INLINE void deepRequestRandomize (Control&) {} @@ -123,7 +117,7 @@ struct S_ final { HFSM_INLINE void deepChangeToRequested(Control&) {} - //---------------------------------------------------------------------- + //------------------------------------------------------------------------------ #if defined _DEBUG || defined HFSM_ENABLE_STRUCTURE_REPORT || defined HFSM_ENABLE_LOG_INTERFACE @@ -134,7 +128,6 @@ struct S_ final { //---------------------------------------------------------------------- #ifdef HFSM_ENABLE_STRUCTURE_REPORT - using StructureStateInfos = typename TArgs::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -144,7 +137,19 @@ struct S_ final { const RegionType region, const ShortIndex depth, StructureStateInfos& stateInfos) const; +#endif + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename TArgs::WriteStream; + using ReadStream = typename TArgs::ReadStream; + + HFSM_INLINE void deepSaveActive (const Registry&, WriteStream&) const {} + HFSM_INLINE void deepSaveResumable(const Registry&, WriteStream&) const {} + HFSM_INLINE void deepLoadRequested( Registry&, ReadStream& ) const {} + HFSM_INLINE void deepLoadResumable( Registry&, ReadStream& ) const {} #endif //---------------------------------------------------------------------- diff --git a/include/hfsm2/detail/structure/state.inl b/include/hfsm2/detail/structure/state.inl index 4665cd6..088fbf9 100644 --- a/include/hfsm2/detail/structure/state.inl +++ b/include/hfsm2/detail/structure/state.inl @@ -37,11 +37,11 @@ struct RegisterT> { template void -S_::deepRegister(StateRegistry& stateRegistry, +S_::deepRegister(Registry& registry, const Parent parent) { using Register = RegisterT; - Register::execute(stateRegistry.stateParents, parent); + Register::execute(registry.stateParents, parent); } //------------------------------------------------------------------------------ diff --git a/include/hfsm2/machine.hpp b/include/hfsm2/machine.hpp index 63b9191..fbb51b7 100644 --- a/include/hfsm2/machine.hpp +++ b/include/hfsm2/machine.hpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk // // Licensed under the MIT License; @@ -189,6 +189,14 @@ struct EmptyPayload {}; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#ifdef HFSM_ENABLE_SERIALIZATION + #define HFSM_IF_SERIALIZATION(...) __VA_ARGS__ +#else + #define HFSM_IF_SERIALIZATION(...) +#endif + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + #if defined _MSC_VER || defined __clang_major__ && __clang_major__ >= 7 #define HFSM_EXPLICIT_MEMBER_SPECIALIZATION #endif @@ -263,7 +271,7 @@ min(const T t1, const T t2) { return t1 < t2 ? t1 : t2; } //------------------------------------------------------------------------------ template -struct UnsignedT { +struct UnsignedCapacityT { static constexpr LongIndex CAPACITY = NCapacity; using Type = typename std::conditional -using Unsigned = typename UnsignedT::Type; +using UnsignedCapacity = typename UnsignedCapacityT::Type; + +//------------------------------------------------------------------------------ + +template +struct UnsignedBitWidthT { + static constexpr ShortIndex BIT_WIDTH = NBitWidth; + + using Type = typename std::conditional::type>::type>::type; + + static_assert(BIT_WIDTH <= 64, "STATIC ASSERT"); +}; + +template +using UnsignedBitWidth = typename UnsignedBitWidthT::Type; //------------------------------------------------------------------------------ @@ -292,14 +317,39 @@ roundUp(const LongIndex x, constexpr ShortIndex bitWidth(const ShortIndex x) { - return x < 2 ? 1 : - x < 4 ? 2 : - x < 8 ? 3 : - x < 16 ? 4 : - x < 32 ? 5 : - x < 64 ? 6 : - x < 128 ? 7 : - 8 ; + return x <= 2 ? 1 : + x <= 4 ? 2 : + x <= 8 ? 3 : + x <= 16 ? 4 : + x <= 32 ? 5 : + x <= 64 ? 6 : + x <= 128 ? 7 : + 8 ; +} + +//------------------------------------------------------------------------------ + +template +void +overwrite(TTo& to, const TFrom& from) { + static_assert(sizeof(TTo) == sizeof(TFrom), "STATIC ASSERT"); + +#if defined(__GNUC__) || defined(__GNUG__) + memcpy (&to, &from, sizeof(from)); +#else + memcpy_s(&to, sizeof(to), &from, sizeof(from)); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +TO convert(const TI& in) { + TO out; + + overwrite(out, in); + + return out; } //////////////////////////////////////////////////////////////////////////////// @@ -457,7 +507,7 @@ class StaticArray { static constexpr LongIndex DUMMY = INVALID_LONG_INDEX; using Item = T; - using Index = Unsigned; + using Index = UnsignedCapacity; public: HFSM_INLINE StaticArray() = default; @@ -469,6 +519,7 @@ class StaticArray { HFSM_INLINE LongIndex count() const { return CAPACITY; } HFSM_INLINE void fill(const Item filler); + HFSM_INLINE void clear() { fill(INVALID_SHORT_INDEX); } HFSM_INLINE Iterator< StaticArray> begin() { return Iterator< StaticArray>(*this, 0); } HFSM_INLINE Iterator begin() const { return Iterator(*this, 0); } @@ -760,6 +811,7 @@ template BitArray::Bits::operator bool() const { const ShortIndex fullUnits = _width / (sizeof(Unit) * 8); + // TODO: cover this case for (Index i = 0; i < fullUnits; ++i) if (_storage[i]) return true; @@ -1072,6 +1124,170 @@ BitArray::bits(const Units& units) const { namespace hfsm2 { namespace detail { +//------------------------------------------------------------------------------ + +template +struct StreamBuffer { + static constexpr LongIndex BIT_CAPACITY = NBitCapacity; + static constexpr LongIndex BYTE_COUNT = roundUp(BIT_CAPACITY, 8); + + using Size = UnsignedCapacity; + using Data = uint8_t[BYTE_COUNT]; + + void clear(); + + //Size write(const uint8_t byte); + + Size bitSize; + Data payload; +}; + +//////////////////////////////////////////////////////////////////////////////// + +template +class BitWriteStream final { +public: + static constexpr LongIndex BIT_CAPACITY = NBitCapacity; + + using Buffer = StreamBuffer; + +public: + BitWriteStream(Buffer& _buffer); + + template + void write(const UnsignedBitWidth item); + +private: + Buffer& _buffer; +}; + +//------------------------------------------------------------------------------ + +template +class BitReadStream final { +public: + static constexpr LongIndex BIT_CAPACITY = NBitCapacity; + + using Buffer = StreamBuffer; + +public: + BitReadStream(const Buffer& buffer) + : _buffer{buffer} + {} + + template + UnsignedBitWidth read(); + + LongIndex cursor() const { return _cursor; } + +private: + const Buffer& _buffer; + + LongIndex _cursor = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// + +} +} + + +namespace hfsm2 { +namespace detail { + +//////////////////////////////////////////////////////////////////////////////// + +template +void +StreamBuffer::clear() { + bitSize = 0; + fill(payload, 0); +} + +//////////////////////////////////////////////////////////////////////////////// + +template +BitWriteStream::BitWriteStream(Buffer& buffer) + : _buffer{buffer} +{ + _buffer.clear(); +} + +//------------------------------------------------------------------------------ + +template +template +void +BitWriteStream::write(const UnsignedBitWidth item) { + constexpr ShortIndex BIT_WIDTH = NBitWidth; + static_assert(BIT_WIDTH > 0, "STATIC ASSERT"); + + HFSM_ASSERT(_buffer.bitSize + BIT_WIDTH < BIT_CAPACITY); + + using Item = UnsignedBitWidth; + + Item itemBits = item; + + for (ShortIndex itemWidth = BIT_WIDTH; itemWidth; ) { + const LongIndex byteIndex = _buffer.bitSize >> 3; + uint8_t& byte = _buffer.payload[byteIndex]; + + const ShortIndex byteChunkStart = _buffer.bitSize & 0x7; + const ShortIndex byteDataWidth = 8 - byteChunkStart; + const ShortIndex byteChunkWidth = detail::min(byteDataWidth, itemWidth); + const Item byteChunk = itemBits << byteChunkStart; + byte |= byteChunk; + + itemBits >>= byteChunkWidth; + itemWidth -= byteChunkWidth; + _buffer.bitSize += byteChunkWidth; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +template +template +UnsignedBitWidth +BitReadStream::read() { + constexpr ShortIndex BIT_WIDTH = NBitWidth; + static_assert(BIT_WIDTH > 0, "STATIC ASSERT"); + + using Item = UnsignedBitWidth; + + Item item = 0; + ShortIndex itemCursor = 0; + + for (ShortIndex itemWidth = BIT_WIDTH; itemWidth; ) + if (HFSM_CHECKED(_cursor + itemWidth <= _buffer.bitSize)) { + const LongIndex byteIndex = _cursor >> 3; + const uint8_t& byte = _buffer.payload[byteIndex]; + + const ShortIndex byteChunkStart = _cursor & 0x7; + const ShortIndex byteDataWidth = 8 - byteChunkStart; + const ShortIndex byteChunkWidth = detail::min(byteDataWidth, itemWidth); + const ShortIndex byteChunkMask = (1 << byteChunkWidth) - 1; + const Item byteChunk = (byte >> byteChunkStart) & byteChunkMask; + + const Item itemChunk = byteChunk << itemCursor; + item |= itemChunk; + + _cursor += byteChunkWidth; + itemCursor += byteChunkWidth; + itemWidth -= byteChunkWidth; + } + + return item; +} + +//////////////////////////////////////////////////////////////////////////////// + +} +} + +namespace hfsm2 { +namespace detail { + //////////////////////////////////////////////////////////////////////////////// template @@ -1412,23 +1628,6 @@ namespace hfsm2 { namespace detail { -template -TO convert(const TI& in) { - static_assert(sizeof(TI) == sizeof(TO), ""); - - TO out; - -#if defined(__GNUC__) || defined(__GNUG__) - memcpy (&out, &in, sizeof(in)); -#else - memcpy_s(&out, sizeof(out), &in, sizeof(in)); -#endif - - return out; -} - -//------------------------------------------------------------------------------ - inline float uniformReal(const uint32_t uint) { @@ -2149,6 +2348,7 @@ template struct ArgsT; @@ -2164,6 +2364,7 @@ template struct PlanDataT> { using StateList = TStateList; @@ -2213,6 +2415,7 @@ struct PlanDataT> { #ifdef HFSM_ENABLE_ASSERT @@ -2233,9 +2436,9 @@ namespace detail { #ifdef HFSM_ENABLE_ASSERT -template +template void -PlanDataT>::verifyPlans() const { +PlanDataT>::verifyPlans() const { LongIndex planCount = 0; for (RegionID id = 0; id < REGION_COUNT; ++id) planCount += verifyPlan(id); @@ -2245,9 +2448,9 @@ PlanDataT>::verifyPlans() co //------------------------------------------------------------------------------ -template +template LongIndex -PlanDataT>::verifyPlan(const RegionID regionId) const { +PlanDataT>::verifyPlan(const RegionID regionId) const { LongIndex length = 0; const Bounds& bounds = tasksBounds[regionId]; @@ -2873,19 +3076,14 @@ using RequestsT = Array; //////////////////////////////////////////////////////////////////////////////// -template -struct AllForksT { - static constexpr ShortIndex COMPO_REGIONS = NCompoCount; - static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; - static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; - - using Compo = StaticArray; - using Ortho = BitArray ; - - Compo compo{INVALID_SHORT_INDEX}; - Ortho ortho; +template +struct BackUpT { + using CompoForks = typename TRegistry::CompoForks; + using OrthoForks = typename TRegistry::OrthoForks; - HFSM_INLINE void clear(); + CompoForks compoRequested; + OrthoForks orthoRequested; + CompoForks compoResumable; }; //////////////////////////////////////////////////////////////////////////////// @@ -2897,11 +3095,12 @@ template struct ArgsT; template -struct StateRegistryT; +struct RegistryT; //------------------------------------------------------------------------------ @@ -2912,23 +3111,25 @@ template -struct StateRegistryT> +struct RegistryT> { using StateList = TStateList; using RegionList = TRegionList; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex COMPO_REGIONS = NCompoCount; - static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; - static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex COMPO_REGIONS = NCompoCount; + static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; + static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; using StateParents = StaticArray; @@ -2937,10 +3138,11 @@ struct StateRegistryT; using CompoForks = StaticArray; - using AllForks = AllForksT; - using OrthoBits = typename AllForks::Ortho::Bits; + using OrthoForks = BitArray ; + using OrthoBits = typename OrthoForks::Bits; + using CompoRemains = BitArray ; - using CompoRemains = BitArray; + using BackUp = BackUpT; bool isActive (const StateID stateId) const; bool isResumable (const StateID stateId) const; @@ -2957,16 +3159,18 @@ struct StateRegistryT -struct StateRegistryT> +struct RegistryT> { using StateList = TStateList; using RegionList = TRegionList; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex COMPO_REGIONS = NCompoCount; + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex COMPO_REGIONS = NCompoCount; using StateParents = StaticArray; using CompoParents = StaticArray; using CompoForks = StaticArray; - using AllForks = AllForksT; - using CompoRemains = BitArray; + using OrthoForks = BitArray ; + using CompoRemains = BitArray ; + + using BackUp = BackUpT; bool isActive (const StateID stateId) const; bool isResumable (const StateID stateId) const; @@ -3013,40 +3221,53 @@ struct StateRegistryT +void +backup(const TRegistry& registry, BackUpT& copy) { + overwrite(copy.compoRequested, registry.compoRequested); + overwrite(copy.orthoRequested, registry.orthoRequested); + overwrite(copy.compoResumable, registry.compoResumable); } +//------------------------------------------------------------------------------ -namespace hfsm2 { -namespace detail { +template +void +restore(TRegistry& registry, const BackUpT& copy) { + overwrite(registry.compoRequested, copy.compoRequested); + overwrite(registry.orthoRequested, copy.orthoRequested); + overwrite(registry.compoResumable, copy.compoResumable); +} //////////////////////////////////////////////////////////////////////////////// -template -void -AllForksT::clear() { - compo.fill(INVALID_SHORT_INDEX); - ortho.clear(); } +} + + +namespace hfsm2 { +namespace detail { //////////////////////////////////////////////////////////////////////////////// -template +template bool -StateRegistryT>::isActive(const StateID stateId) const { +RegistryT>::isActive(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) for (Parent parent = stateParents[stateId]; parent; @@ -3063,9 +3284,9 @@ StateRegistryT>::isActive(co // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template bool -StateRegistryT>::isResumable(const StateID stateId) const { +RegistryT>::isResumable(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) for (Parent parent = stateParents[stateId]; parent; @@ -3074,7 +3295,7 @@ StateRegistryT>::isResumable HFSM_ASSERT(parent.forkId != 0); if (parent.forkId > 0) - return parent.prong == resumable[parent.forkId - 1]; + return parent.prong == compoResumable[parent.forkId - 1]; } return false; @@ -3082,9 +3303,9 @@ StateRegistryT>::isResumable //------------------------------------------------------------------------------ -template +template bool -StateRegistryT>::isPendingChange(const StateID stateId) const { +RegistryT>::isPendingChange(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) for (Parent parent = stateParents[stateId]; parent; @@ -3093,8 +3314,8 @@ StateRegistryT>::isPendingCh HFSM_ASSERT(parent.forkId != 0); if (parent.forkId > 0) - return requested.compo[parent.forkId - 1] != - compoActive[parent.forkId - 1]; + return compoRequested[parent.forkId - 1] != + compoActive [parent.forkId - 1]; } return true; @@ -3102,9 +3323,9 @@ StateRegistryT>::isPendingCh // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template bool -StateRegistryT>::isPendingEnter(const StateID stateId) const { +RegistryT>::isPendingEnter(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) for (Parent parent = stateParents[stateId]; parent; @@ -3113,8 +3334,8 @@ StateRegistryT>::isPendingEn HFSM_ASSERT(parent.forkId != 0); if (parent.forkId > 0) - return parent.prong != compoActive[parent.forkId - 1] && - parent.prong == requested.compo[parent.forkId - 1]; + return parent.prong != compoActive [parent.forkId - 1] && + parent.prong == compoRequested[parent.forkId - 1]; } return true; @@ -3122,9 +3343,9 @@ StateRegistryT>::isPendingEn // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template bool -StateRegistryT>::isPendingExit(const StateID stateId) const { +RegistryT>::isPendingExit(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) for (Parent parent = stateParents[stateId]; parent; @@ -3133,8 +3354,8 @@ StateRegistryT>::isPendingEx HFSM_ASSERT(parent.forkId != 0); if (parent.forkId > 0) - return parent.prong == compoActive[parent.forkId - 1] && - parent.prong != requested.compo[parent.forkId - 1]; + return parent.prong == compoActive [parent.forkId - 1] && + parent.prong != compoRequested[parent.forkId - 1]; } return true; @@ -3142,9 +3363,9 @@ StateRegistryT>::isPendingEx //------------------------------------------------------------------------------ -template +template const Parent& -StateRegistryT>::forkParent(const ForkID forkId) const { +RegistryT>::forkParent(const ForkID forkId) const { HFSM_ASSERT(forkId != 0); return forkId > 0 ? @@ -3154,20 +3375,20 @@ StateRegistryT>::forkParent( //------------------------------------------------------------------------------ -template -typename StateRegistryT>::OrthoBits -StateRegistryT>::requestedOrthoFork(const ForkID forkId) { +template +typename RegistryT>::OrthoBits +RegistryT>::requestedOrthoFork(const ForkID forkId) { HFSM_ASSERT(forkId < 0); const Units& units = orthoUnits[-forkId - 1]; - return requested.ortho.bits(units); + return orthoRequested.bits(units); } //------------------------------------------------------------------------------ -template +template bool -StateRegistryT>::requestImmediate(const Request request) { +RegistryT>::requestImmediate(const Request request) { if (request.stateId == 0) return false; else if (HFSM_CHECKED(request.stateId < STATE_COUNT)) { @@ -3178,7 +3399,7 @@ StateRegistryT>::requestImme parent = forkParent(parent.forkId)) { if (parent.forkId > 0) { - requested.compo[parent.forkId - 1] = parent.prong; + compoRequested[parent.forkId - 1] = parent.prong; parent = forkParent(parent.forkId); break; @@ -3192,8 +3413,8 @@ StateRegistryT>::requestImme if (parent.forkId > 0) { compoRemains.set(parent.forkId - 1); - if ( compoActive[parent.forkId - 1] != parent.prong) - requested.compo[parent.forkId - 1] = parent.prong; + if (compoActive [parent.forkId - 1] != parent.prong) + compoRequested[parent.forkId - 1] = parent.prong; else { parent = forkParent(parent.forkId); break; @@ -3219,14 +3440,14 @@ StateRegistryT>::requestImme // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template void -StateRegistryT>::requestScheduled(const StateID stateId) { +RegistryT>::requestScheduled(const StateID stateId) { if (HFSM_CHECKED(stateId < STATE_COUNT)) { const Parent parent = stateParents[stateId]; if (parent.forkId > 0) - resumable[parent.forkId - 1] = parent.prong; + compoResumable[parent.forkId - 1] = parent.prong; else HFSM_BREAK(); } @@ -3234,18 +3455,31 @@ StateRegistryT>::requestSche //------------------------------------------------------------------------------ -template +template void -StateRegistryT>::clearRequests() { - compoRemains.clear(); - requested.clear(); +RegistryT>::clearRequests() { + compoRequested.clear(); + orthoRequested.clear(); + compoRemains .clear(); +} + +//------------------------------------------------------------------------------ + +template +void +RegistryT>::reset() { + compoRequested.clear(); + orthoRequested.clear(); + compoActive .clear(); + compoResumable.clear(); + compoRemains .clear(); } //////////////////////////////////////////////////////////////////////////////// -template +template bool -StateRegistryT>::isActive(const StateID stateId) const { +RegistryT>::isActive(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) { if (Parent parent = stateParents[stateId]) { HFSM_ASSERT(parent.forkId > 0); @@ -3260,14 +3494,14 @@ StateRegistryT>::isActive(const St // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template bool -StateRegistryT>::isResumable(const StateID stateId) const { +RegistryT>::isResumable(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) if (Parent parent = stateParents[stateId]) { HFSM_ASSERT(parent.forkId > 0); - return parent.prong == resumable[parent.forkId - 1]; + return parent.prong == compoResumable[parent.forkId - 1]; } return false; @@ -3275,15 +3509,15 @@ StateRegistryT>::isResumable(const //------------------------------------------------------------------------------ -template +template bool -StateRegistryT>::isPendingChange(const StateID stateId) const { +RegistryT>::isPendingChange(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) if (Parent parent = stateParents[stateId]) { HFSM_ASSERT(parent.forkId > 0); - return requested.compo[parent.forkId - 1] != - compoActive[parent.forkId - 1]; + return compoRequested[parent.forkId - 1] != + compoActive [parent.forkId - 1]; } return false; @@ -3291,15 +3525,15 @@ StateRegistryT>::isPendingChange(c // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template bool -StateRegistryT>::isPendingEnter(const StateID stateId) const { +RegistryT>::isPendingEnter(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) if (Parent parent = stateParents[stateId]) { HFSM_ASSERT(parent.forkId > 0); - return parent.prong != compoActive[parent.forkId - 1] && - parent.prong == requested.compo[parent.forkId - 1]; + return parent.prong != compoActive [parent.forkId - 1] && + parent.prong == compoRequested[parent.forkId - 1]; } return false; @@ -3307,15 +3541,15 @@ StateRegistryT>::isPendingEnter(co // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template bool -StateRegistryT>::isPendingExit(const StateID stateId) const { +RegistryT>::isPendingExit(const StateID stateId) const { if (HFSM_CHECKED(stateId < STATE_COUNT)) if (Parent parent = stateParents[stateId]) { HFSM_ASSERT(parent.forkId > 0); - return parent.prong == compoActive[parent.forkId - 1] && - parent.prong != requested.compo[parent.forkId - 1]; + return parent.prong == compoActive [parent.forkId - 1] && + parent.prong != compoRequested[parent.forkId - 1]; } return false; @@ -3323,9 +3557,9 @@ StateRegistryT>::isPendingExit(con //------------------------------------------------------------------------------ -template +template const Parent& -StateRegistryT>::forkParent(const ForkID forkId) const { +RegistryT>::forkParent(const ForkID forkId) const { HFSM_ASSERT(forkId > 0); return compoParents[forkId - 1]; @@ -3333,9 +3567,9 @@ StateRegistryT>::forkParent(const //------------------------------------------------------------------------------ -template +template bool -StateRegistryT>::requestImmediate(const Request request) { +RegistryT>::requestImmediate(const Request request) { if (request.stateId == 0) return false; else if (HFSM_CHECKED(request.stateId < STATE_COUNT)) { @@ -3344,7 +3578,7 @@ StateRegistryT>::requestImmediate( if (HFSM_CHECKED(parent)) { HFSM_ASSERT(parent.forkId > 0); - requested.compo[parent.forkId - 1] = parent.prong; + compoRequested[parent.forkId - 1] = parent.prong; for (parent = forkParent(parent.forkId); parent; @@ -3353,8 +3587,8 @@ StateRegistryT>::requestImmediate( HFSM_ASSERT(parent.forkId > 0); compoRemains.set(parent.forkId - 1); - if ( compoActive[parent.forkId - 1] != parent.prong) - requested.compo[parent.forkId - 1] = parent.prong; + if (compoActive [parent.forkId - 1] != parent.prong) + compoRequested[parent.forkId - 1] = parent.prong; else { parent = forkParent(parent.forkId); break; @@ -3373,26 +3607,39 @@ StateRegistryT>::requestImmediate( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -template +template void -StateRegistryT>::requestScheduled(const StateID stateId) { +RegistryT>::requestScheduled(const StateID stateId) { HFSM_ASSERT(stateId < STATE_COUNT); if (stateId < STATE_COUNT) { const Parent parent = stateParents[stateId]; if (HFSM_CHECKED(parent.forkId > 0)) - resumable[parent.forkId - 1] = parent.prong; + compoResumable[parent.forkId - 1] = parent.prong; } } //------------------------------------------------------------------------------ -template +template void -StateRegistryT>::clearRequests() { - compoRemains.clear(); - requested.clear(); +RegistryT>::clearRequests() { + compoRequested.clear(); + orthoRequested.clear(); + compoRemains .clear(); +} + +//------------------------------------------------------------------------------ + +template +void +RegistryT>::reset() { + compoRequested.clear(); + orthoRequested.clear(); + compoActive .clear(); + compoResumable.clear(); + compoRemains .clear(); } //////////////////////////////////////////////////////////////////////////////// @@ -3428,7 +3675,7 @@ class ControlT { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; + using Registry = RegistryT; using PlanData = PlanDataT; using ConstPlan = ConstPlanT; @@ -3448,12 +3695,12 @@ class ControlT { HFSM_INLINE ControlT(Context& context, RNG& rng, - StateRegistry& stateRegistry, + Registry& registry, PlanData& planData, Logger* const HFSM_IF_LOGGER(logger)) : _context{context} , _rng{rng} - , _stateRegistry{stateRegistry} + , _registry{registry} , _planData{planData} HFSM_IF_LOGGER(, _logger{logger}) {} @@ -3474,8 +3721,8 @@ class ControlT { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE bool isActive (const StateID id) const { return _stateRegistry.isActive (id); } - HFSM_INLINE bool isResumable(const StateID id) const { return _stateRegistry.isResumable(id); } + HFSM_INLINE bool isActive (const StateID id) const { return _registry.isActive (id); } + HFSM_INLINE bool isResumable(const StateID id) const { return _registry.isResumable(id); } HFSM_INLINE bool isScheduled(const StateID id) const { return isResumable(id); } @@ -3507,7 +3754,7 @@ class ControlT { protected: Context& _context; RNG& _rng; - StateRegistry& _stateRegistry; + Registry& _registry; PlanData& _planData; RegionID _regionId = 0; HFSM_IF_LOGGER(Logger* _logger); @@ -3652,7 +3899,7 @@ class FullControlT using typename PlanControl::Plan; using typename PlanControl::Origin; - using StateRegistry = StateRegistryT; + using Registry = RegistryT; using Requests = RequestsT; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3668,11 +3915,11 @@ class FullControlT HFSM_INLINE FullControlT(Context& context, RNG& rng, - StateRegistry& stateRegistry, + Registry& registry, PlanData& planData, Requests& requests, Logger* const logger) - : PlanControl{context, rng, stateRegistry, planData, logger} + : PlanControl{context, rng, registry, planData, logger} , _requests{requests} {} @@ -3768,7 +4015,7 @@ class GuardControlT final using typename FullControl::RegionList; using typename FullControl::PlanData; - using typename FullControl::StateRegistry; + using typename FullControl::Registry; protected: using Requests = RequestsT; @@ -3778,12 +4025,12 @@ class GuardControlT final private: HFSM_INLINE GuardControlT(Context& context, RNG& rng, - StateRegistry& stateRegistry, + Registry& registry, PlanData& planData, Requests& requests, const Requests& pendingChanges, Logger* const logger) - : FullControl{context, rng, stateRegistry, planData, requests, logger} + : FullControl{context, rng, registry, planData, requests, logger} , _pending{pendingChanges} {} @@ -3813,9 +4060,9 @@ class GuardControlT final // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE bool isPendingChange(const StateID id) const { return _stateRegistry.isPendingChange(id); } - HFSM_INLINE bool isPendingEnter (const StateID id) const { return _stateRegistry.isPendingEnter (id); } - HFSM_INLINE bool isPendingExit (const StateID id) const { return _stateRegistry.isPendingExit (id); } + HFSM_INLINE bool isPendingChange(const StateID id) const { return _registry.isPendingChange(id); } + HFSM_INLINE bool isPendingEnter (const StateID id) const { return _registry.isPendingEnter (id); } + HFSM_INLINE bool isPendingExit (const StateID id) const { return _registry.isPendingExit (id); } template HFSM_INLINE bool isPendingChange() { return isPendingChange(FullControl::template stateId()); } @@ -3835,7 +4082,7 @@ class GuardControlT final private: HFSM_IF_LOGGER(using FullControl::_logger); - using FullControl::_stateRegistry; + using FullControl::_registry; using FullControl::_originId; bool _cancelled = false; @@ -4849,8 +5096,8 @@ struct S_ final { using Logger = typename TArgs::Logger; using Control = ControlT; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using PlanControl = PlanControlT; using ScopedOrigin = typename PlanControl::Origin; @@ -4864,7 +5111,6 @@ struct S_ final { //---------------------------------------------------------------------- #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnull-dereference" @@ -4880,29 +5126,24 @@ struct S_ final { #pragma clang diagnostic pop #endif - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template <> struct Accessor { HFSM_INLINE static Head& get( S_& s) { return s._headBox.get(); } HFSM_INLINE static const Head& get(const S_& s) { return s._headBox.get(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template HFSM_INLINE T& access() { return Accessor::get(*this); } template HFSM_INLINE const T& access() const { return Accessor::get(*this); } - #endif //---------------------------------------------------------------------- - HFSM_INLINE Parent stateParent (Control& control) { return control._stateRegistry.stateParents[STATE_ID]; } + HFSM_INLINE Parent stateParent (Control& control) { return control._registry.stateParents[STATE_ID]; } - HFSM_INLINE void deepRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void deepRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -4941,9 +5182,9 @@ struct S_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void deepRequestChange (Control&) {} - HFSM_INLINE void deepRequestRemain (StateRegistry&) {} - HFSM_INLINE void deepRequestRestart (StateRegistry&) {} - HFSM_INLINE void deepRequestResume (StateRegistry&) {} + HFSM_INLINE void deepRequestRemain (Registry&) {} + HFSM_INLINE void deepRequestRestart (Registry&) {} + HFSM_INLINE void deepRequestResume (Registry&) {} HFSM_INLINE void deepRequestUtilize (Control&) {} HFSM_INLINE void deepRequestRandomize (Control&) {} @@ -4956,7 +5197,7 @@ struct S_ final { HFSM_INLINE void deepChangeToRequested(Control&) {} - //---------------------------------------------------------------------- + //------------------------------------------------------------------------------ #if defined _DEBUG || defined HFSM_ENABLE_STRUCTURE_REPORT || defined HFSM_ENABLE_LOG_INTERFACE @@ -4967,7 +5208,6 @@ struct S_ final { //---------------------------------------------------------------------- #ifdef HFSM_ENABLE_STRUCTURE_REPORT - using StructureStateInfos = typename TArgs::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -4977,7 +5217,19 @@ struct S_ final { const RegionType region, const ShortIndex depth, StructureStateInfos& stateInfos) const; +#endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename TArgs::WriteStream; + using ReadStream = typename TArgs::ReadStream; + + HFSM_INLINE void deepSaveActive (const Registry&, WriteStream&) const {} + HFSM_INLINE void deepSaveResumable(const Registry&, WriteStream&) const {} + + HFSM_INLINE void deepLoadRequested( Registry&, ReadStream& ) const {} + HFSM_INLINE void deepLoadResumable( Registry&, ReadStream& ) const {} #endif //---------------------------------------------------------------------- @@ -5087,11 +5339,11 @@ struct RegisterT> { template void -S_::deepRegister(StateRegistry& stateRegistry, +S_::deepRegister(Registry& registry, const Parent parent) { using Register = RegisterT; - Register::execute(stateRegistry.stateParents, parent); + Register::execute(registry.stateParents, parent); } //------------------------------------------------------------------------------ @@ -5470,15 +5722,18 @@ struct SI_ final { using StateList = TL_; using RegionList = TL_<>; - static constexpr ShortIndex WIDTH = 1; - static constexpr LongIndex REVERSE_DEPTH = 1; - static constexpr ShortIndex COMPO_REGIONS = 0; - static constexpr LongIndex COMPO_PRONGS = 0; - static constexpr ShortIndex ORTHO_REGIONS = 0; - static constexpr ShortIndex ORTHO_UNITS = 0; + static constexpr ShortIndex WIDTH = 1; + static constexpr LongIndex REVERSE_DEPTH = 1; + static constexpr ShortIndex COMPO_REGIONS = 0; + static constexpr LongIndex COMPO_PRONGS = 0; + static constexpr ShortIndex ORTHO_REGIONS = 0; + static constexpr ShortIndex ORTHO_UNITS = 0; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = 0; + static constexpr LongIndex RESUMABLE_BITS = 0; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5490,14 +5745,17 @@ struct CSI_ { using StateList = Merge; using RegionList = Merge; - static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = Max::VALUE; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS + Remaining::RESUMABLE_BITS; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; template @@ -5506,14 +5764,17 @@ struct CSI_ { using StateList = typename Initial::StateList; using RegionList = typename Initial::RegionList; - static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = Initial::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; template @@ -5526,15 +5787,19 @@ struct CI_ final { using StateList = Merge; using RegionList = Merge; - static constexpr ShortIndex WIDTH = sizeof...(TSubStates); - static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; - static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS + 1; - static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS + WIDTH; - static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS; + static constexpr ShortIndex WIDTH = sizeof...(TSubStates); + static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; + static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS + 1; + static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS + WIDTH; + static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS; + + static constexpr LongIndex WIDTH_BITS = bitWidth(WIDTH); + static constexpr LongIndex ACTIVE_BITS = SubStates::ACTIVE_BITS + WIDTH_BITS; + static constexpr LongIndex RESUMABLE_BITS = SubStates::RESUMABLE_BITS + WIDTH_BITS + 1; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5546,11 +5811,14 @@ struct OSI_ { using StateList = Merge; using RegionList = Merge; - static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Max::VALUE; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS + Remaining::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS + Remaining::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS + Remaining::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS + Remaining::ORTHO_UNITS; + + static constexpr LongIndex ACTIVE_BITS = Initial::ACTIVE_BITS + Remaining::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS + Remaining::RESUMABLE_BITS; }; template @@ -5559,11 +5827,14 @@ struct OSI_ { using StateList = typename Initial::StateList; using RegionList = typename Initial::RegionList; - static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; - static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; - static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; + static constexpr LongIndex REVERSE_DEPTH = Initial::REVERSE_DEPTH; + static constexpr ShortIndex COMPO_REGIONS = Initial::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = Initial::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = Initial::ORTHO_REGIONS; + static constexpr ShortIndex ORTHO_UNITS = Initial::ORTHO_UNITS; + + static constexpr LongIndex ACTIVE_BITS = Initial::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Initial::RESUMABLE_BITS; }; template @@ -5574,15 +5845,18 @@ struct OI_ final { using StateList = Merge; using RegionList = Merge; - static constexpr ShortIndex WIDTH = sizeof...(TSubStates); - static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; - static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS; - static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS; - static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS + 1; - static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS + (WIDTH + 7) / 8; + static constexpr ShortIndex WIDTH = sizeof...(TSubStates); + static constexpr LongIndex REVERSE_DEPTH = SubStates::REVERSE_DEPTH + 1; + static constexpr ShortIndex COMPO_REGIONS = SubStates::COMPO_REGIONS; + static constexpr LongIndex COMPO_PRONGS = SubStates::COMPO_PRONGS; + static constexpr ShortIndex ORTHO_REGIONS = SubStates::ORTHO_REGIONS + 1; + static constexpr ShortIndex ORTHO_UNITS = SubStates::ORTHO_UNITS + (WIDTH + 7) / 8; - static constexpr LongIndex STATE_COUNT = StateList::SIZE; - static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; + static constexpr LongIndex ACTIVE_BITS = SubStates::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = SubStates::RESUMABLE_BITS; + + static constexpr LongIndex STATE_COUNT = StateList::SIZE; + static constexpr ShortIndex REGION_COUNT = RegionList::SIZE; }; //////////////////////////////////////////////////////////////////////////////// @@ -5594,6 +5868,7 @@ template struct ArgsT final { using Context = TContext; @@ -5612,8 +5887,16 @@ struct ArgsT final { static constexpr ShortIndex COMPO_REGIONS = NCompoCount; static constexpr ShortIndex ORTHO_REGIONS = NOrthoCount; static constexpr ShortIndex ORTHO_UNITS = NOrthoUnits; + static constexpr ShortIndex SERIAL_BITS = NSerialBits; + static constexpr LongIndex TASK_CAPACITY = NTaskCapacity; +#ifdef HFSM_ENABLE_SERIALIZATION + using SerialBuffer = StreamBuffer ; + using WriteStream = BitWriteStream; + using ReadStream = BitReadStream ; +#endif + HFSM_IF_STRUCTURE(using StructureStateInfos = Array); }; @@ -5703,6 +5986,9 @@ struct RF_ final { static constexpr ShortIndex ORTHO_REGIONS = Apex::ORTHO_REGIONS; static constexpr ShortIndex ORTHO_UNITS = Apex::ORTHO_UNITS; + static constexpr LongIndex ACTIVE_BITS = Apex::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = Apex::RESUMABLE_BITS; + using StateList = Indexed; using RegionList = Indexed; @@ -5713,6 +5999,7 @@ struct RF_ final { COMPO_REGIONS, ORTHO_REGIONS, ORTHO_UNITS, + ACTIVE_BITS + RESUMABLE_BITS, TASK_CAPACITY>; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5838,8 +6125,8 @@ struct CS_ final { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using Control = ControlT ; using PlanControl = PlanControlT ; @@ -5874,18 +6161,16 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access(); template HFSM_INLINE const T& access() const; - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void wideRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5938,9 +6223,9 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry, const ShortIndex prong); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry, const ShortIndex prong); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5959,6 +6244,8 @@ struct CS_ final { HFSM_INLINE void wideChangeToRequested (PlanControl& control, const ShortIndex prong); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -5971,11 +6258,26 @@ struct CS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream ) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream ) const; +#endif + + //---------------------------------------------------------------------- + LHalf lHalf; RHalf rHalf; }; -//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// template final { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using Control = ControlT ; using PlanControl = PlanControlT ; @@ -6019,18 +6321,16 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access() { return state.template access(); } template HFSM_INLINE const T& access() const { return state.template access(); } - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void wideRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -6066,9 +6366,9 @@ struct CS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry, const ShortIndex prong); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry, const ShortIndex prong); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -6087,6 +6387,8 @@ struct CS_ final { HFSM_INLINE void wideChangeToRequested (PlanControl& control, const ShortIndex prong); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -6099,6 +6401,21 @@ struct CS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream ) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream, const ShortIndex prong) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream ) const; +#endif + + //---------------------------------------------------------------------- + State state; }; @@ -6140,11 +6457,11 @@ CS_::access() const { template void -CS_::wideRegister(StateRegistry& stateRegistry, +CS_::wideRegister(Registry& registry, const Parent parent) { - lHalf.wideRegister(stateRegistry, Parent{parent.forkId, L_PRONG}); - rHalf.wideRegister(stateRegistry, Parent{parent.forkId, R_PRONG}); + lHalf.wideRegister(registry, Parent{parent.forkId, L_PRONG}); + rHalf.wideRegister(registry, Parent{parent.forkId, R_PRONG}); } //------------------------------------------------------------------------------ @@ -6371,31 +6688,31 @@ CS_::wideRequestChangeResumable(Control& control, template void -CS_::wideRequestRemain(StateRegistry& stateRegistry) { - lHalf.wideRequestRemain(stateRegistry); +CS_::wideRequestRemain(Registry& registry) { + lHalf.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestRestart(StateRegistry& stateRegistry) { - lHalf.wideRequestRestart(stateRegistry); +CS_::wideRequestRestart(Registry& registry) { + lHalf.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestResume(StateRegistry& stateRegistry, +CS_::wideRequestResume(Registry& registry, const ShortIndex prong) { HFSM_ASSERT(prong != INVALID_SHORT_INDEX); if (prong < R_PRONG) - lHalf.wideRequestResume(stateRegistry, prong); + lHalf.wideRequestResume(registry, prong); else - rHalf.wideRequestResume(stateRegistry, prong); + rHalf.wideRequestResume(registry, prong); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -6527,21 +6844,85 @@ CS_::wideGetNames(const LongIndex parent, #endif -//////////////////////////////////////////////////////////////////////////////// - -} -} -namespace hfsm2 { -namespace detail { +//------------------------------------------------------------------------------ -//////////////////////////////////////////////////////////////////////////////// +#ifdef HFSM_ENABLE_SERIALIZATION -template +template void -CS_::wideRegister(StateRegistry& stateRegistry, - const Parent parent) +CS_::wideSaveActive(const Registry& registry, + WriteStream& stream, + const ShortIndex prong) const { - state.deepRegister(stateRegistry, Parent{parent.forkId, PRONG_INDEX}); + HFSM_ASSERT(prong != INVALID_SHORT_INDEX); + + if (prong < R_PRONG) { + lHalf.wideSaveActive (registry, stream, prong); + rHalf.wideSaveResumable(registry, stream); + } else { + lHalf.wideSaveResumable(registry, stream); + rHalf.wideSaveActive (registry, stream, prong); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + lHalf.wideSaveResumable(registry, stream); + rHalf.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadRequested(Registry& registry, + ReadStream& stream, + const ShortIndex prong) const +{ + HFSM_ASSERT(prong != INVALID_SHORT_INDEX); + + if (prong < R_PRONG) { + lHalf.wideLoadRequested(registry, stream, prong); + rHalf.wideLoadResumable(registry, stream); + } else { + lHalf.wideLoadResumable(registry, stream); + rHalf.wideLoadRequested(registry, stream, prong); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + lHalf.wideLoadResumable(registry, stream); + rHalf.wideLoadResumable(registry, stream); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +} +} +namespace hfsm2 { +namespace detail { + +//////////////////////////////////////////////////////////////////////////////// + +template +void +CS_::wideRegister(Registry& registry, + const Parent parent) +{ + state.deepRegister(registry, Parent{parent.forkId, PRONG_INDEX}); } //------------------------------------------------------------------------------ @@ -6728,28 +7109,28 @@ CS_::wideRequestChangeResumable(Control& control, template void -CS_::wideRequestRemain(StateRegistry& stateRegistry) { - state.deepRequestRemain(stateRegistry); +CS_::wideRequestRemain(Registry& registry) { + state.deepRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestRestart(StateRegistry& stateRegistry) { - state.deepRequestRestart(stateRegistry); +CS_::wideRequestRestart(Registry& registry) { + state.deepRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -CS_::wideRequestResume(StateRegistry& stateRegistry, +CS_::wideRequestResume(Registry& registry, const ShortIndex HFSM_IF_ASSERT(prong)) { HFSM_ASSERT(prong == PRONG_INDEX); - state.deepRequestResume(stateRegistry); + state.deepRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -6864,6 +7245,56 @@ CS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +CS_::wideSaveActive(const Registry& registry, + WriteStream& stream, + const ShortIndex HFSM_IF_ASSERT(prong)) const +{ + HFSM_ASSERT(prong == PRONG_INDEX); + + state.deepSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + state.deepSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadRequested(Registry& registry, + ReadStream& stream, + const ShortIndex HFSM_IF_ASSERT(prong)) const +{ + HFSM_ASSERT(prong == PRONG_INDEX); + + state.deepLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +CS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + state.deepLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } @@ -6897,8 +7328,8 @@ struct C_ final { using StateList = typename Args::StateList; using RegionList = typename Args::RegionList; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; using Control = ControlT; @@ -6926,53 +7357,59 @@ struct C_ final { TSubStates...>; using Info = CI_; - static constexpr ShortIndex REGION_SIZE = Info::STATE_COUNT; + static constexpr ShortIndex WIDTH = Info::WIDTH; + static constexpr ShortIndex WIDTH_BITS = Info::WIDTH_BITS; + static constexpr ShortIndex STATE_COUNT = Info::STATE_COUNT; //---------------------------------------------------------------------- #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template struct Accessor { - HFSM_INLINE static T& get( C_& c) { return c._subStates.template access(); } - HFSM_INLINE static const T& get(const C_& c) { return c._subStates.template access(); } + HFSM_INLINE static T& get( C_& c) { return c._subStates.template access(); } + HFSM_INLINE static const T& get(const C_& c) { return c._subStates.template access(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template <> struct Accessor { - HFSM_INLINE static Head& get( C_& c) { return c._headState._headBox.get(); } - HFSM_INLINE static const Head& get(const C_& c) { return c._headState._headBox.get(); } + HFSM_INLINE static Head& get( C_& c) { return c._headState._headBox.get(); } + HFSM_INLINE static const Head& get(const C_& c) { return c._headState._headBox.get(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - HFSM_INLINE T& access() { return Accessor::get(*this); } + HFSM_INLINE T& access() { return Accessor::get(*this); } template - HFSM_INLINE const T& access() const { return Accessor::get(*this); } - + HFSM_INLINE const T& access() const { return Accessor::get(*this); } #endif //---------------------------------------------------------------------- - HFSM_INLINE ShortIndex& compoActive (StateRegistry& stateRegistry) { return stateRegistry.compoActive [COMPO_INDEX]; } - HFSM_INLINE ShortIndex& compoResumable(StateRegistry& stateRegistry) { return stateRegistry.resumable [COMPO_INDEX]; } - HFSM_INLINE ShortIndex& compoRequested(StateRegistry& stateRegistry) { return stateRegistry.requested.compo[COMPO_INDEX]; } + HFSM_INLINE ShortIndex& compoRequested( Registry& registry) const { return registry.compoRequested[COMPO_INDEX]; } + HFSM_INLINE const ShortIndex& compoRequested(const Registry& registry) const { return registry.compoRequested[COMPO_INDEX]; } + + HFSM_INLINE ShortIndex& compoActive ( Registry& registry) const { return registry.compoActive [COMPO_INDEX]; } + HFSM_INLINE const ShortIndex& compoActive (const Registry& registry) const { return registry.compoActive [COMPO_INDEX]; } + + HFSM_INLINE ShortIndex& compoResumable( Registry& registry) const { return registry.compoResumable[COMPO_INDEX]; } + HFSM_INLINE const ShortIndex& compoResumable(const Registry& registry) const { return registry.compoResumable[COMPO_INDEX]; } - HFSM_INLINE ShortIndex& compoActive (Control& control) { return compoActive (control._stateRegistry); } - HFSM_INLINE ShortIndex& compoResumable(Control& control) { return compoResumable(control._stateRegistry); } - HFSM_INLINE ShortIndex& compoRequested(Control& control) { return compoRequested(control._stateRegistry); } + HFSM_INLINE ShortIndex& compoRequested( Control& control) const { return compoRequested(control._registry); } + HFSM_INLINE const ShortIndex& compoRequested(const Control& control) const { return compoRequested(control._registry); } - HFSM_INLINE ShortIndex resolveRandom (Control& control, - const Utility(& options)[Info::WIDTH], const Utility sum, - const Rank (& ranks) [Info::WIDTH], const Rank top); + HFSM_INLINE ShortIndex& compoActive ( Control& control) const { return compoActive (control._registry); } + HFSM_INLINE const ShortIndex& compoActive (const Control& control) const { return compoActive (control._registry); } - HFSM_INLINE bool compoRemain (Control& control) { return control._stateRegistry.compoRemains.template get(); } + HFSM_INLINE ShortIndex& compoResumable( Control& control) const { return compoResumable(control._registry); } + HFSM_INLINE const ShortIndex& compoResumable(const Control& control) const { return compoResumable(control._registry); } - HFSM_INLINE void deepRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE ShortIndex resolveRandom (Control& control, + const Utility(& options)[Info::WIDTH], const Utility sum, + const Rank (& ranks) [Info::WIDTH], const Rank top) const; + + HFSM_INLINE bool compoRemain (Control& control) { return control._registry.compoRemains.template get(); } + + HFSM_INLINE void deepRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7035,9 +7472,9 @@ struct C_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void deepRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void deepRequestRemain (Registry& registry); + HFSM_INLINE void deepRequestRestart (Registry& registry); + HFSM_INLINE void deepRequestResume (Registry& registry); HFSM_INLINE void deepRequestUtilize (Control& control); HFSM_INLINE void deepRequestRandomize (Control& control); @@ -7081,6 +7518,8 @@ struct C_ final { HFSM_INLINE void deepChangeToRequested (PlanControl& control); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; using RegionType = typename StructureStateInfo::RegionType; @@ -7093,6 +7532,21 @@ struct C_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void deepSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void deepSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void deepLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void deepLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + HeadState _headState; SubStates _subStates; @@ -7115,7 +7569,7 @@ C_::resolveRandom(Control& control, const Utility(& options)[Info::WIDTH], const Utility sum, const Rank(& ranks)[Info::WIDTH], - const Rank top) + const Rank top) const { const Utility random = control._rng.next(); HFSM_ASSERT(0.0f <= random && random < 1.0f); @@ -7143,13 +7597,13 @@ C_::resolveRandom(Control& control, template void -C_::deepRegister(StateRegistry& stateRegistry, +C_::deepRegister(Registry& registry, const Parent parent) { - stateRegistry.compoParents[COMPO_INDEX] = parent; + registry.compoParents[COMPO_INDEX] = parent; - _headState.deepRegister(stateRegistry, parent); - _subStates.wideRegister(stateRegistry, Parent{COMPO_ID}); + _headState.deepRegister(registry, parent); + _subStates.wideRegister(registry, Parent{COMPO_ID}); } //------------------------------------------------------------------------------ @@ -7162,7 +7616,7 @@ C_::deepForwardEntryGuard(GuardControl& control) { HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (requested == INVALID_SHORT_INDEX) return _subStates.wideForwardEntryGuard(control, active); @@ -7178,7 +7632,7 @@ C_::deepEntryGuard(GuardControl& control) { const ShortIndex requested = compoRequested(control); HFSM_ASSERT(requested != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; return _headState.deepEntryGuard(control) || _subStates.wideEntryGuard(control, requested); @@ -7214,7 +7668,7 @@ void C_::deepEnter(PlanControl& control) { const ShortIndex& active = compoActive(control); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; _headState.deepEnter(control); _subStates.wideEnter(control, active); @@ -7232,7 +7686,7 @@ C_::deepReenter(PlanControl& control) { HFSM_ASSERT(active != INVALID_SHORT_INDEX && requested != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; _headState.deepReenter(control); @@ -7260,7 +7714,7 @@ C_::deepUpdate(FullControl& control) { const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion outer{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion outer{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (const Status headStatus = _headState.deepUpdate(control)) { ControlLock lock{control}; @@ -7273,7 +7727,7 @@ C_::deepUpdate(FullControl& control) { if (subStatus.outerTransition) return Status{Status::NONE, true}; - ScopedRegion inner{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion inner{control, REGION_ID, HEAD_ID, STATE_COUNT}; return subStatus && control._planData.planExists.template get() ? control.updatePlan(_headState, subStatus) : subStatus; @@ -7291,7 +7745,7 @@ C_::deepReact(FullControl& control, const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion outer{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion outer{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (const Status headStatus = _headState.deepReact(control, event)) { ControlLock lock{control}; @@ -7304,7 +7758,7 @@ C_::deepReact(FullControl& control, if (subStatus.outerTransition) return subStatus; - ScopedRegion inner{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion inner{control, REGION_ID, HEAD_ID, STATE_COUNT}; return subStatus && control._planData.planExists.template get() ? control.updatePlan(_headState, subStatus) : subStatus; @@ -7319,7 +7773,7 @@ C_::deepForwardExitGuard(GuardControl& control) { const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; if (compoRequested(control) == INVALID_SHORT_INDEX) return _subStates.wideForwardExitGuard(control, active); @@ -7335,7 +7789,7 @@ C_::deepExitGuard(GuardControl& control) { const ShortIndex active = compoActive(control); HFSM_ASSERT(active != INVALID_SHORT_INDEX); - ScopedRegion region{control, REGION_ID, HEAD_ID, REGION_SIZE}; + ScopedRegion region{control, REGION_ID, HEAD_ID, STATE_COUNT}; return _headState.deepExitGuard(control) || _subStates.wideExitGuard(control, active); @@ -7380,7 +7834,7 @@ void C_::deepForwardActive(Control& control, const Request::Type request) { - HFSM_ASSERT(control._stateRegistry.isActive(HEAD_ID)); + HFSM_ASSERT(control._registry.isActive(HEAD_ID)); const ShortIndex requested = compoRequested(control); @@ -7416,7 +7870,7 @@ C_::deepRequest(Control& control, { switch (request) { case Request::REMAIN: - deepRequestRemain (control._stateRegistry); + deepRequestRemain (control._registry); break; case Request::CHANGE: @@ -7424,11 +7878,11 @@ C_::deepRequest(Control& control, break; case Request::RESTART: - deepRequestRestart (control._stateRegistry); + deepRequestRestart (control._registry); break; case Request::RESUME: - deepRequestResume (control._stateRegistry); + deepRequestResume (control._registry); break; case Request::UTILIZE: @@ -7536,40 +7990,40 @@ C_::deepRequestChangeRandom(Control& control) { template void -C_::deepRequestRemain(StateRegistry& stateRegistry) { - const ShortIndex active = compoActive (stateRegistry); - ShortIndex& requested = compoRequested(stateRegistry); +C_::deepRequestRemain(Registry& registry) { + const ShortIndex active = compoActive (registry); + ShortIndex& requested = compoRequested(registry); if (active == INVALID_SHORT_INDEX) requested = 0; - _subStates.wideRequestRemain(stateRegistry); + _subStates.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -C_::deepRequestRestart(StateRegistry& stateRegistry) { - ShortIndex& requested = compoRequested(stateRegistry); +C_::deepRequestRestart(Registry& registry) { + ShortIndex& requested = compoRequested(registry); requested = 0; - _subStates.wideRequestRestart(stateRegistry); + _subStates.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -C_::deepRequestResume(StateRegistry& stateRegistry) { - const ShortIndex resumable = compoResumable(stateRegistry); - ShortIndex& requested = compoRequested(stateRegistry); +C_::deepRequestResume(Registry& registry) { + const ShortIndex resumable = compoResumable(registry); + ShortIndex& requested = compoRequested(registry); requested = (resumable != INVALID_SHORT_INDEX) ? resumable : 0; - _subStates.wideRequestResume(stateRegistry, requested); + _subStates.wideRequestResume(registry, requested); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7812,6 +8266,89 @@ C_::deepGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +C_::deepSaveActive(const Registry& registry, + WriteStream& stream) const +{ + const ShortIndex active = compoActive (registry); + const ShortIndex resumable = compoResumable(registry); + + stream.template write(active); + + if (resumable != INVALID_SHORT_INDEX) { + stream.template write<1>(1); + stream.template write(resumable); + } else + stream.template write<1>(0); + + _subStates.wideSaveActive(registry,stream, active); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +C_::deepSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + const ShortIndex resumable = compoResumable(registry); + + if (resumable != INVALID_SHORT_INDEX) { + stream.template write<1>(1); + stream.template write(resumable); + } else + stream.template write<1>(0); + + _subStates.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +C_::deepLoadRequested(Registry& registry, + ReadStream& stream) const +{ + ShortIndex& resumable = compoResumable(registry); + ShortIndex& requested = compoRequested(registry); + + requested = stream.template read(); + HFSM_ASSERT(requested < WIDTH); + + if (stream.template read<1>()) { + resumable = stream.template read(); + HFSM_ASSERT(resumable < WIDTH); + } else + resumable = INVALID_SHORT_INDEX; + + _subStates.wideLoadRequested(registry, stream, requested); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +C_::deepLoadResumable(Registry& registry, + ReadStream& stream) const +{ + ShortIndex& resumable = compoResumable(registry); + + if (stream.template read<1>()) { + resumable = stream.template read(); + HFSM_ASSERT(resumable < WIDTH); + } else + resumable = INVALID_SHORT_INDEX; + + _subStates.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } @@ -7845,9 +8382,9 @@ struct OS_ final { using Utility = typename Args::Utility; using UP = typename Args::UP; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; - using OrthoForks = typename StateRegistry::AllForks::Ortho; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; + using OrthoForks = typename Registry::OrthoForks; using ProngBits = typename OrthoForks::Bits; using ProngConstBits= typename OrthoForks::ConstBits; @@ -7879,18 +8416,16 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access(); template HFSM_INLINE const T& access() const; - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const ForkID forkId); + HFSM_INLINE void wideRegister (Registry& registry, const ForkID forkId); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7924,9 +8459,9 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestChange (Control& control); - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry); HFSM_INLINE void wideRequestUtilize (Control& control); HFSM_INLINE void wideRequestRandomize (Control& control); @@ -7938,6 +8473,8 @@ struct OS_ final { HFSM_INLINE void wideChangeToRequested(PlanControl& control); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; @@ -7948,11 +8485,26 @@ struct OS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + Initial initial; Remaining remaining; }; -//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// template final { using Utility = typename Args::Utility; using UP = typename Args::UP; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; - using OrthoForks = typename StateRegistry::AllForks::Ortho; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; + using OrthoForks = typename Registry::OrthoForks; using ProngBits = typename OrthoForks::Bits; using ProngConstBits= typename OrthoForks::ConstBits; @@ -7995,18 +8547,16 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template HFSM_INLINE T& access() { return initial.template access(); } template HFSM_INLINE const T& access() const { return initial.template access(); } - #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRegister (StateRegistry& stateRegistry, const ForkID forkId); + HFSM_INLINE void wideRegister (Registry& registry, const ForkID forkId); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8040,9 +8590,9 @@ struct OS_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void wideRequestChange (Control& control); - HFSM_INLINE void wideRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void wideRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void wideRequestRemain (Registry& registry); + HFSM_INLINE void wideRequestRestart (Registry& registry); + HFSM_INLINE void wideRequestResume (Registry& registry); HFSM_INLINE void wideRequestUtilize (Control& control); HFSM_INLINE void wideRequestRandomize (Control& control); @@ -8054,6 +8604,8 @@ struct OS_ final { HFSM_INLINE void wideChangeToRequested(PlanControl& control); + //---------------------------------------------------------------------- + #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; @@ -8064,6 +8616,21 @@ struct OS_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void wideSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void wideSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void wideLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void wideLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + Initial initial; }; @@ -8105,11 +8672,11 @@ OS_::access() const { template void -OS_::wideRegister(StateRegistry& stateRegistry, +OS_::wideRegister(Registry& registry, const ForkID forkId) { - initial .deepRegister(stateRegistry, Parent{forkId, PRONG_INDEX}); - remaining.wideRegister(stateRegistry, forkId); + initial .deepRegister(registry, Parent{forkId, PRONG_INDEX}); + remaining.wideRegister(registry, forkId); } //------------------------------------------------------------------------------ @@ -8295,27 +8862,27 @@ OS_::wideRequestChange(Control& control) { template void -OS_::wideRequestRemain(StateRegistry& stateRegistry) { - initial .deepRequestRemain(stateRegistry); - remaining.wideRequestRemain(stateRegistry); +OS_::wideRequestRemain(Registry& registry) { + initial .deepRequestRemain(registry); + remaining.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestRestart(StateRegistry& stateRegistry) { - initial .deepRequestRestart(stateRegistry); - remaining.wideRequestRestart(stateRegistry); +OS_::wideRequestRestart(Registry& registry) { + initial .deepRequestRestart(registry); + remaining.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestResume(StateRegistry& stateRegistry) { - initial .deepRequestResume(stateRegistry); - remaining.wideRequestResume(stateRegistry); +OS_::wideRequestResume(Registry& registry) { + initial .deepRequestResume(registry); + remaining.wideRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8394,6 +8961,54 @@ OS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +OS_::wideSaveActive(const Registry& registry, + WriteStream& stream) const +{ + initial .deepSaveActive(registry, stream); + remaining.wideSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + initial .deepSaveResumable(registry, stream); + remaining.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadRequested(Registry& registry, + ReadStream& stream) const +{ + initial .deepLoadRequested(registry, stream); + remaining.wideLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + initial .deepLoadResumable(registry, stream); + remaining.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } @@ -8405,10 +9020,10 @@ namespace detail { template void -OS_::wideRegister(StateRegistry& stateRegistry, +OS_::wideRegister(Registry& registry, const ForkID forkId) { - initial.deepRegister(stateRegistry, Parent{forkId, PRONG_INDEX}); + initial.deepRegister(registry, Parent{forkId, PRONG_INDEX}); } //------------------------------------------------------------------------------ @@ -8564,24 +9179,24 @@ OS_::wideRequestChange(Control& control) { template void -OS_::wideRequestRemain(StateRegistry& stateRegistry) { - initial.deepRequestRemain(stateRegistry); +OS_::wideRequestRemain(Registry& registry) { + initial.deepRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestRestart(StateRegistry& stateRegistry) { - initial.deepRequestRestart(stateRegistry); +OS_::wideRequestRestart(Registry& registry) { + initial.deepRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -OS_::wideRequestResume(StateRegistry& stateRegistry) { - initial.deepRequestResume(stateRegistry); +OS_::wideRequestResume(Registry& registry) { + initial.deepRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8653,6 +9268,50 @@ OS_::wideGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +OS_::wideSaveActive(const Registry& registry, + WriteStream& stream) const +{ + initial.deepSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + initial.deepSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadRequested(Registry& registry, + ReadStream& stream) const +{ + initial.deepLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +OS_::wideLoadResumable(Registry& registry, + ReadStream& stream) const +{ + initial.deepLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } @@ -8690,9 +9349,9 @@ struct O_ final { static constexpr ShortIndex REGION_SIZE = Info::STATE_COUNT; static constexpr ShortIndex ORTHO_UNITS = Info::ORTHO_UNITS; - using StateRegistry = StateRegistryT; - using StateParents = typename StateRegistry::StateParents; - using OrthoForks = typename StateRegistry::AllForks::Ortho; + using Registry = RegistryT; + using StateParents = typename Registry::StateParents; + using OrthoForks = typename Registry::OrthoForks; using ProngBits = typename OrthoForks::Bits; using ProngConstBits= typename OrthoForks::ConstBits; @@ -8720,40 +9379,34 @@ struct O_ final { //---------------------------------------------------------------------- #ifdef HFSM_EXPLICIT_MEMBER_SPECIALIZATION - template struct Accessor { - HFSM_INLINE static T& get( O_& o) { return o._subStates.template access(); } - HFSM_INLINE static const T& get(const O_& o) { return o._subStates.template access(); } + HFSM_INLINE static T& get( O_& o) { return o._subStates.template access(); } + HFSM_INLINE static const T& get(const O_& o) { return o._subStates.template access(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template <> struct Accessor { - HFSM_INLINE static Head& get( O_& o) { return o._headState._headBox.get(); } - HFSM_INLINE static const Head& get(const O_& o) { return o._headState._headBox.get(); } + HFSM_INLINE static Head& get( O_& o) { return o._headState._headBox.get(); } + HFSM_INLINE static const Head& get(const O_& o) { return o._headState._headBox.get(); } }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - HFSM_INLINE T& access() { return Accessor::get(*this); } + HFSM_INLINE T& access() { return Accessor::get(*this); } template - HFSM_INLINE const T& access() const { return Accessor::get(*this); } - + HFSM_INLINE const T& access() const { return Accessor::get(*this); } #endif //---------------------------------------------------------------------- - HFSM_INLINE ProngBits orthoRequested( StateRegistry& stateRegistry) { return stateRegistry.requested.ortho.template bits(); } - HFSM_INLINE ProngConstBits orthoRequested(const StateRegistry& stateRegistry) const { return stateRegistry.requested.ortho.template bits(); } + HFSM_INLINE ProngBits orthoRequested( Registry& registry) { return registry.orthoRequested.template bits(); } + HFSM_INLINE ProngConstBits orthoRequested(const Registry& registry) const { return registry.orthoRequested.template bits(); } - HFSM_INLINE ProngBits orthoRequested( Control& control) { return orthoRequested(control._stateRegistry); } - HFSM_INLINE ProngConstBits orthoRequested(const Control& control) const { return orthoRequested(control._stateRegistry); } + HFSM_INLINE ProngBits orthoRequested( Control& control) { return orthoRequested(control._registry); } + HFSM_INLINE ProngConstBits orthoRequested(const Control& control) const { return orthoRequested(control._registry); } - HFSM_INLINE void deepRegister (StateRegistry& stateRegistry, const Parent parent); + HFSM_INLINE void deepRegister (Registry& registry, const Parent parent); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8787,9 +9440,9 @@ struct O_ final { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void deepRequestChange (Control& control); - HFSM_INLINE void deepRequestRemain (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestRestart (StateRegistry& stateRegistry); - HFSM_INLINE void deepRequestResume (StateRegistry& stateRegistry); + HFSM_INLINE void deepRequestRemain (Registry& registry); + HFSM_INLINE void deepRequestRestart (Registry& registry); + HFSM_INLINE void deepRequestResume (Registry& registry); HFSM_INLINE void deepRequestUtilize (Control& control); HFSM_INLINE void deepRequestRandomize (Control& control); @@ -8802,7 +9455,7 @@ struct O_ final { HFSM_INLINE void deepChangeToRequested(PlanControl& control); - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + //---------------------------------------------------------------------- #ifdef HFSM_ENABLE_STRUCTURE_REPORT using StructureStateInfos = typename Args::StructureStateInfos; @@ -8816,6 +9469,21 @@ struct O_ final { StructureStateInfos& stateInfos) const; #endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; + + HFSM_INLINE void deepSaveActive (const Registry& registry, WriteStream& stream) const; + HFSM_INLINE void deepSaveResumable(const Registry& registry, WriteStream& stream) const; + + HFSM_INLINE void deepLoadRequested( Registry& registry, ReadStream& stream) const; + HFSM_INLINE void deepLoadResumable( Registry& registry, ReadStream& stream) const; +#endif + + //---------------------------------------------------------------------- + HeadState _headState; SubStates _subStates; }; @@ -8832,14 +9500,14 @@ namespace detail { template void -O_::deepRegister(StateRegistry& stateRegistry, +O_::deepRegister(Registry& registry, const Parent parent) { - stateRegistry.orthoParents[ORTHO_INDEX] = parent; - stateRegistry.orthoUnits[ORTHO_INDEX] = Units{ORTHO_UNIT, WIDTH}; + registry.orthoParents[ORTHO_INDEX] = parent; + registry.orthoUnits[ORTHO_INDEX] = Units{ORTHO_UNIT, WIDTH}; - _headState.deepRegister(stateRegistry, parent); - _subStates.wideRegister(stateRegistry, ORTHO_ID); + _headState.deepRegister(registry, parent); + _subStates.wideRegister(registry, ORTHO_ID); } //------------------------------------------------------------------------------ @@ -9009,7 +9677,7 @@ void O_::deepForwardActive(Control& control, const Request::Type request) { - HFSM_ASSERT(control._stateRegistry.isActive(HEAD_ID)); + HFSM_ASSERT(control._registry.isActive(HEAD_ID)); const ProngConstBits requested = orthoRequested(static_cast(control)); HFSM_ASSERT(!!requested); @@ -9041,7 +9709,7 @@ O_::deepRequest(Control& control, { switch (request) { case Request::REMAIN: - deepRequestRemain (control._stateRegistry); + deepRequestRemain (control._registry); break; case Request::CHANGE: @@ -9049,11 +9717,11 @@ O_::deepRequest(Control& control, break; case Request::RESTART: - deepRequestRestart(control._stateRegistry); + deepRequestRestart(control._registry); break; case Request::RESUME: - deepRequestResume (control._stateRegistry); + deepRequestResume (control._registry); break; case Request::UTILIZE: @@ -9081,24 +9749,24 @@ O_::deepRequestChange(Control& control) { template void -O_::deepRequestRemain(StateRegistry& stateRegistry) { - _subStates.wideRequestRemain(stateRegistry); +O_::deepRequestRemain(Registry& registry) { + _subStates.wideRequestRemain(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -O_::deepRequestRestart(StateRegistry& stateRegistry) { - _subStates.wideRequestRestart(stateRegistry); +O_::deepRequestRestart(Registry& registry) { + _subStates.wideRequestRestart(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template void -O_::deepRequestResume(StateRegistry& stateRegistry) { - _subStates.wideRequestResume(stateRegistry); +O_::deepRequestResume(Registry& registry) { + _subStates.wideRequestResume(registry); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9201,6 +9869,50 @@ O_::deepGetNames(const LongIndex parent, #endif +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +O_::deepSaveActive(const Registry& registry, + WriteStream& stream) const +{ + _subStates.wideSaveActive(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +O_::deepSaveResumable(const Registry& registry, + WriteStream& stream) const +{ + _subStates.wideSaveResumable(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +O_::deepLoadRequested(Registry& registry, + ReadStream& stream) const +{ + _subStates.wideLoadRequested(registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +O_::deepLoadResumable(Registry& registry, + ReadStream& stream) const +{ + _subStates.wideLoadResumable(registry, stream); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// } @@ -9727,8 +10439,8 @@ class R_ { using Logger = typename Config_::Logger; using Apex = TApex; - using ApexInfo = WrapInfo; + using Info = RF_; using StateList = typename Info::StateList; using RegionList = typename Info::RegionList; @@ -9743,6 +10455,9 @@ class R_ { static constexpr ShortIndex ORTHO_REGIONS = ApexInfo::ORTHO_REGIONS; static constexpr ShortIndex ORTHO_UNITS = ApexInfo::ORTHO_UNITS; + static constexpr LongIndex ACTIVE_BITS = ApexInfo::ACTIVE_BITS; + static constexpr LongIndex RESUMABLE_BITS = ApexInfo::RESUMABLE_BITS; + static constexpr LongIndex STATE_COUNT = ApexInfo::STATE_COUNT; static constexpr LongIndex REGION_COUNT = ApexInfo::REGION_COUNT; @@ -9752,9 +10467,9 @@ class R_ { private: using Args = typename Info::Args; - using StateRegistry = StateRegistryT; - using CompoForks = typename StateRegistry::CompoForks; - using AllForks = typename StateRegistry::AllForks; + using Registry = RegistryT; + using CompoForks = typename Registry::CompoForks; + using RegistryBackUp = typename Registry::BackUp; using MaterialApex = Material, Args, Apex>; @@ -9768,23 +10483,26 @@ class R_ { using GuardControl = GuardControlT; -public: - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef HFSM_ENABLE_STRUCTURE_REPORT - using StructureStateInfos = typename Args::StructureStateInfos; - static constexpr LongIndex NAME_COUNT = MaterialApex::NAME_COUNT; using Prefix = StaticArray; using Prefixes = StaticArray; - using Structure = Array; - using ActivityHistory = Array; + using StructureStateInfos = typename Args::StructureStateInfos; #endif -#ifdef HFSM_ENABLE_TRANSITION_HISTORY - using TransitionHistory = Array; +#ifdef HFSM_ENABLE_SERIALIZATION + using WriteStream = typename Args::WriteStream; + using ReadStream = typename Args::ReadStream; +#endif + +public: + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +#ifdef HFSM_ENABLE_STRUCTURE_REPORT + using Structure = Array; + using ActivityHistory = Array; #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9799,10 +10517,10 @@ class R_ { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - static constexpr StateID stateId() { return StateList ::template index(); } + static constexpr StateID stateId() { return StateList ::template index(); } template - static constexpr RegionID regionId() { return (RegionID) RegionList::template index(); } + static constexpr RegionID regionId() { return (RegionID) RegionList::template index(); } //---------------------------------------------------------------------- @@ -9822,8 +10540,8 @@ class R_ { template struct Accessor { - HFSM_INLINE static T& get( MaterialApex& apex) { return apex.template access(); } - HFSM_INLINE static const T& get(const MaterialApex& apex) { return apex.template access(); } + HFSM_INLINE static T& get( MaterialApex& apex) { return apex.template access(); } + HFSM_INLINE static const T& get(const MaterialApex& apex) { return apex.template access(); } }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9835,20 +10553,20 @@ class R_ { // .. you're trying to access() a type that is not present in the state machine hierarchy template - HFSM_INLINE T& access() { return Accessor::get(_apex); } + HFSM_INLINE T& access() { return Accessor::get(_apex); } template - HFSM_INLINE const T& access() const { return Accessor::get(_apex); } + HFSM_INLINE const T& access() const { return Accessor::get(_apex); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #else template - HFSM_INLINE T& access() { return Accessor{_apex}.get(); } + HFSM_INLINE T& access() { return Accessor{_apex}.get(); } template - HFSM_INLINE const T& access() const { return Accessor{_apex}.get(); } + HFSM_INLINE const T& access() const { return Accessor{_apex}.get(); } #endif @@ -9861,19 +10579,19 @@ class R_ { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE bool isActive (const StateID stateId) const { return _stateRegistry.isActive (stateId); } - HFSM_INLINE bool isResumable(const StateID stateId) const { return _stateRegistry.isResumable(stateId); } + HFSM_INLINE bool isActive (const StateID stateId) const { return _registry.isActive (stateId); } + HFSM_INLINE bool isResumable(const StateID stateId) const { return _registry.isResumable(stateId); } - HFSM_INLINE bool isScheduled(const StateID stateId) const { return isResumable(stateId); } + HFSM_INLINE bool isScheduled(const StateID stateId) const { return isResumable(stateId); } template - HFSM_INLINE bool isActive () const { return isActive (stateId()); } + HFSM_INLINE bool isActive () const { return isActive (stateId()); } template - HFSM_INLINE bool isResumable() const { return isResumable(stateId()); } + HFSM_INLINE bool isResumable() const { return isResumable(stateId()); } template - HFSM_INLINE bool isScheduled() const { return isResumable(); } + HFSM_INLINE bool isScheduled() const { return isResumable(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9887,42 +10605,58 @@ class R_ { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - HFSM_INLINE void changeTo () { changeTo (stateId()); } + HFSM_INLINE void changeTo () { changeTo (stateId()); } template - HFSM_INLINE void restart () { restart (stateId()); } + HFSM_INLINE void restart () { restart (stateId()); } template - HFSM_INLINE void resume () { resume (stateId()); } + HFSM_INLINE void resume () { resume (stateId()); } template - HFSM_INLINE void utilize () { utilize (stateId()); } + HFSM_INLINE void utilize () { utilize (stateId()); } template - HFSM_INLINE void randomize() { randomize(stateId()); } + HFSM_INLINE void randomize() { randomize(stateId()); } template - HFSM_INLINE void schedule () { schedule (stateId()); } + HFSM_INLINE void schedule () { schedule (stateId()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HFSM_INLINE void clearResumable() { _stateRegistry.resumable.clear(); } - HFSM_INLINE void clearRequests() { _stateRegistry.requested.clear(); } - #ifdef HFSM_ENABLE_STRUCTURE_REPORT - const Structure& structure() const { return _structure; } - const ActivityHistory& activityHistory() const { return _activityHistory; } + const Structure& structure() const { return _structure; } + const ActivityHistory& activityHistory() const { return _activityHistory; } #endif #ifdef HFSM_ENABLE_TRANSITION_HISTORY - const TransitionHistory& transitionHistory() const { return _transitionHistory; } + using TransitionHistory = Array; + + const TransitionHistory& transitionHistory() const { return _transitionHistory; } - void replayTransition (const Transition& transition) { replayTransitions(&transition, 1); } + void replayTransition (const Transition& transition) { replayTransitions(&transition, 1); } void replayTransitions(const Transition* const transitions, const uint64_t count); #endif + void reset(); + +#ifdef HFSM_ENABLE_SERIALIZATION + // Buffer for serialization + // Members: + // bitSize - Number of payload bits used + // payload - Serialized data + // See https://doc.hfsm.dev/user-guide/debugging-and-tools/serialization + using SerialBuffer = typename Args::SerialBuffer; + + // Serialize the structural configuration into 'buffer' + void save( SerialBuffer& buffer) const; + + // De-serialize the configuration and initialize the instance + void load(const SerialBuffer& buffer); +#endif + #if defined HFSM_ENABLE_LOG_INTERFACE || defined HFSM_ENABLE_VERBOSE_DEBUG_LOG - void attachLogger(Logger* const logger) { _logger = logger; } + void attachLogger(Logger* const logger) { _logger = logger; } #endif private: @@ -9952,7 +10686,7 @@ class R_ { Context& _context; RNG& _rng; - StateRegistry _stateRegistry; + Registry _registry; PlanData _planData; Requests _requests; @@ -10086,7 +10820,7 @@ R_::R_(Context& context, , _rng{rng} HFSM_IF_LOGGER(, _logger{logger}) { - _apex.deepRegister(_stateRegistry, Parent{}); + _apex.deepRegister(_registry, Parent{}); HFSM_IF_STRUCTURE(getStateNames()); @@ -10099,7 +10833,7 @@ template R_::~R_() { PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -10116,7 +10850,7 @@ void R_::update() { FullControl control(_context, _rng, - _stateRegistry, + _registry, _planData, _requests, HFSM_LOGGER_OR(_logger, nullptr)); @@ -10138,7 +10872,7 @@ void R_::react(const TEvent& event) { FullControl control{_context, _rng, - _stateRegistry, + _registry, _planData, _requests, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -10226,14 +10960,14 @@ R_::replayTransitions(const Transition* const transitions, PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; if (applyRequests(control, transitions, count)) { _apex.deepChangeToRequested(control); - _stateRegistry.clearRequests(); + _registry.clearRequests(); HFSM_IF_ASSERT(_planData.verifyPlans()); } @@ -10246,21 +10980,76 @@ R_::replayTransitions(const Transition* const transitions, //------------------------------------------------------------------------------ +template +void +R_::reset() { + PlanControl control{_context, + _rng, + _registry, + _planData, + HFSM_LOGGER_OR(_logger, nullptr)}; + + _apex.deepExit (control); + _apex.deepDestruct (control); + + _registry.reset(); + + _apex.deepRequestChange(control); + _apex.deepConstruct(control); + _apex.deepEnter (control); +} + +//------------------------------------------------------------------------------ + +#ifdef HFSM_ENABLE_SERIALIZATION + +template +void +R_::save(SerialBuffer& _buffer) const { + WriteStream stream{_buffer}; + + _apex.deepSaveActive(_registry, stream); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +template +void +R_::load(const SerialBuffer& buffer) { + PlanControl control{_context, + _rng, + _registry, + _planData, + HFSM_LOGGER_OR(_logger, nullptr)}; + + _apex.deepExit (control); + _apex.deepDestruct (control); + + ReadStream stream{buffer}; + _apex.deepLoadRequested(_registry, stream); + + _apex.deepConstruct(control); + _apex.deepEnter (control); +} + +#endif + +//------------------------------------------------------------------------------ + template void R_::initialEnter() { HFSM_ASSERT(_requests.count() == 0); HFSM_IF_TRANSITION_HISTORY(HFSM_ASSERT(_transitionHistory.count() == 0)); - CompoForks undoResumable; - AllForks undoRequested; + RegistryBackUp undo; HFSM_IF_TRANSITION_HISTORY(TransitionHistory undoTransitionHistory); Requests lastRequests; PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -10272,8 +11061,7 @@ R_::initialEnter() { i < SUBSTITUTION_LIMIT && _requests.count(); ++i) { - undoResumable = _stateRegistry.resumable; - undoRequested = _stateRegistry.requested; + backup(_registry, undo); HFSM_IF_TRANSITION_HISTORY(undoTransitionHistory = _transitionHistory); if (applyRequests(control)) { @@ -10281,8 +11069,7 @@ R_::initialEnter() { _requests.clear(); if (cancelledByEntryGuards(lastRequests)) { - _stateRegistry.resumable = undoResumable; - _stateRegistry.requested = undoRequested; + restore(_registry, undo); HFSM_IF_TRANSITION_HISTORY(_transitionHistory = undoTransitionHistory); } } else @@ -10293,7 +11080,7 @@ R_::initialEnter() { _apex.deepConstruct(control); _apex.deepEnter (control); - _stateRegistry.clearRequests(); + _registry.clearRequests(); HFSM_IF_ASSERT(_planData.verifyPlans()); @@ -10309,15 +11096,14 @@ R_::processTransitions() { HFSM_IF_TRANSITION_HISTORY(_transitionHistory.clear()); - CompoForks undoResumable; - AllForks undoRequested; + RegistryBackUp undo; HFSM_IF_TRANSITION_HISTORY(TransitionHistory undoTransitionHistory); Requests lastRequests; PlanControl control{_context, _rng, - _stateRegistry, + _registry, _planData, HFSM_LOGGER_OR(_logger, nullptr)}; @@ -10327,8 +11113,7 @@ R_::processTransitions() { i < SUBSTITUTION_LIMIT && _requests.count(); ++i) { - undoResumable = _stateRegistry.resumable; - undoRequested = _stateRegistry.requested; + backup(_registry, undo); HFSM_IF_TRANSITION_HISTORY(undoTransitionHistory = _transitionHistory); if (applyRequests(control)) { @@ -10336,8 +11121,7 @@ R_::processTransitions() { _requests.clear(); if (cancelledByGuards(lastRequests)) { - _stateRegistry.resumable = undoResumable; - _stateRegistry.requested = undoRequested; + restore(_registry, undo); HFSM_IF_TRANSITION_HISTORY(_transitionHistory = undoTransitionHistory); } else changesMade = true; @@ -10348,7 +11132,7 @@ R_::processTransitions() { if (changesMade) { _apex.deepChangeToRequested(control); - _stateRegistry.clearRequests(); + _registry.clearRequests(); HFSM_IF_ASSERT(_planData.verifyPlans()); } @@ -10369,7 +11153,7 @@ R_::applyRequest(Control& control, const Request& request) { case Request::RESUME: case Request::UTILIZE: case Request::RANDOMIZE: - if (_stateRegistry.requestImmediate(request)) + if (_registry.requestImmediate(request)) _apex.deepForwardActive(control, request.type); else _apex.deepRequest (control, request.type); @@ -10377,7 +11161,7 @@ R_::applyRequest(Control& control, const Request& request) { return true; case Request::SCHEDULE: - _stateRegistry.requestScheduled(request.stateId); + _registry.requestScheduled(request.stateId); return false; @@ -10431,7 +11215,7 @@ bool R_::cancelledByEntryGuards(const Requests& pendingRequests) { GuardControl guardControl{_context, _rng, - _stateRegistry, + _registry, _planData, _requests, pendingRequests, @@ -10452,7 +11236,7 @@ bool R_::cancelledByGuards(const Requests& pendingRequests) { GuardControl guardControl{_context, _rng, - _stateRegistry, + _registry, _planData, _requests, pendingRequests, @@ -10579,7 +11363,7 @@ R_::udpateActivity() { #endif -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +//------------------------------------------------------------------------------ #ifdef HFSM_ENABLE_TRANSITION_HISTORY diff --git a/include/hfsm2/machine_dev.hpp b/include/hfsm2/machine_dev.hpp index ec7be10..9685d99 100644 --- a/include/hfsm2/machine_dev.hpp +++ b/include/hfsm2/machine_dev.hpp @@ -1,4 +1,4 @@ -// HFSM (hierarchical state machine for games and interactive applications) +// HFSM2 (hierarchical state machine for games and interactive applications) // Created by Andrew Gresyk // // Licensed under the MIT License; @@ -68,6 +68,7 @@ struct EmptyPayload {}; #include "detail/shared/iterator.hpp" #include "detail/shared/array.hpp" #include "detail/shared/bit_array.hpp" +#include "detail/shared/bit_stream.hpp" #include "detail/shared/list.hpp" #include "detail/shared/random.hpp" #include "detail/shared/type_list.hpp" @@ -77,7 +78,7 @@ struct EmptyPayload {}; #include "detail/root/plan_data.hpp" #include "detail/root/plan.hpp" -#include "detail/root/state_registry.hpp" +#include "detail/root/registry.hpp" #include "detail/root/control.hpp" #include "detail/debug/structure_report.hpp" diff --git a/projects/code-lite/snippets-gcc-tdm/snippets-gcc-tdm.project b/projects/code-lite/snippets-gcc-tdm/snippets-gcc-tdm.project index 575eae2..00dfb80 100644 --- a/projects/code-lite/snippets-gcc-tdm/snippets-gcc-tdm.project +++ b/projects/code-lite/snippets-gcc-tdm/snippets-gcc-tdm.project @@ -1,17 +1,18 @@ + + + + + + - - - - - diff --git a/projects/code-lite/test-gcc-tdm/test-gcc-tdm.project b/projects/code-lite/test-gcc-tdm/test-gcc-tdm.project index 0fd28a3..b16f25b 100644 --- a/projects/code-lite/test-gcc-tdm/test-gcc-tdm.project +++ b/projects/code-lite/test-gcc-tdm/test-gcc-tdm.project @@ -7,17 +7,19 @@ - - - - - - - - - - - + + + + + + + + + + + + + @@ -37,12 +39,12 @@ + + - - @@ -63,6 +65,8 @@ + + @@ -82,6 +86,7 @@ + diff --git a/projects/visual-studio/snippets-14.vcxproj b/projects/visual-studio/snippets-14.vcxproj index 9f5cac9..b5444fc 100644 --- a/projects/visual-studio/snippets-14.vcxproj +++ b/projects/visual-studio/snippets-14.vcxproj @@ -22,6 +22,7 @@ + diff --git a/projects/visual-studio/snippets-14.vcxproj.filters b/projects/visual-studio/snippets-14.vcxproj.filters index 4ae2d88..9e2b7ca 100644 --- a/projects/visual-studio/snippets-14.vcxproj.filters +++ b/projects/visual-studio/snippets-14.vcxproj.filters @@ -6,6 +6,7 @@ + diff --git a/projects/visual-studio/snippets-15.vcxproj b/projects/visual-studio/snippets-15.vcxproj index 64091c6..73ef059 100644 --- a/projects/visual-studio/snippets-15.vcxproj +++ b/projects/visual-studio/snippets-15.vcxproj @@ -22,6 +22,7 @@ + diff --git a/projects/visual-studio/snippets-15.vcxproj.filters b/projects/visual-studio/snippets-15.vcxproj.filters index 42f27c3..7f1663e 100644 --- a/projects/visual-studio/snippets-15.vcxproj.filters +++ b/projects/visual-studio/snippets-15.vcxproj.filters @@ -11,6 +11,7 @@ + diff --git a/projects/visual-studio/snippets-16.vcxproj b/projects/visual-studio/snippets-16.vcxproj index ee6d4de..6f6d75c 100644 --- a/projects/visual-studio/snippets-16.vcxproj +++ b/projects/visual-studio/snippets-16.vcxproj @@ -22,6 +22,7 @@ + diff --git a/projects/visual-studio/snippets-16.vcxproj.filters b/projects/visual-studio/snippets-16.vcxproj.filters index 649d1c0..17611ad 100644 --- a/projects/visual-studio/snippets-16.vcxproj.filters +++ b/projects/visual-studio/snippets-16.vcxproj.filters @@ -6,6 +6,7 @@ + diff --git a/projects/visual-studio/snippets-clang.vcxproj b/projects/visual-studio/snippets-clang.vcxproj index d1601f6..8183bcd 100644 --- a/projects/visual-studio/snippets-clang.vcxproj +++ b/projects/visual-studio/snippets-clang.vcxproj @@ -22,6 +22,7 @@ + diff --git a/projects/visual-studio/snippets-clang.vcxproj.filters b/projects/visual-studio/snippets-clang.vcxproj.filters index f7a9af2..2468b7e 100644 --- a/projects/visual-studio/snippets-clang.vcxproj.filters +++ b/projects/visual-studio/snippets-clang.vcxproj.filters @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/projects/visual-studio/test-14.vcxproj b/projects/visual-studio/test-14.vcxproj index d678eef..6e012a3 100644 --- a/projects/visual-studio/test-14.vcxproj +++ b/projects/visual-studio/test-14.vcxproj @@ -21,6 +21,7 @@ + @@ -41,6 +42,7 @@ + @@ -53,10 +55,11 @@ + - + @@ -78,9 +81,10 @@ - + + diff --git a/projects/visual-studio/test-14.vcxproj.filters b/projects/visual-studio/test-14.vcxproj.filters index 2d93e96..64962fe 100644 --- a/projects/visual-studio/test-14.vcxproj.filters +++ b/projects/visual-studio/test-14.vcxproj.filters @@ -87,6 +87,12 @@ test + + test\shared + + + test + @@ -161,12 +167,15 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + @@ -223,11 +232,14 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + \ No newline at end of file diff --git a/projects/visual-studio/test-15.vcxproj b/projects/visual-studio/test-15.vcxproj index e6d4ac1..7406b54 100644 --- a/projects/visual-studio/test-15.vcxproj +++ b/projects/visual-studio/test-15.vcxproj @@ -21,6 +21,7 @@ + @@ -36,6 +37,7 @@ + @@ -48,10 +50,11 @@ + - + @@ -73,9 +76,10 @@ - + + diff --git a/projects/visual-studio/test-15.vcxproj.filters b/projects/visual-studio/test-15.vcxproj.filters index f71a5e1..9e3c3a4 100644 --- a/projects/visual-studio/test-15.vcxproj.filters +++ b/projects/visual-studio/test-15.vcxproj.filters @@ -87,6 +87,12 @@ test + + test\shared + + + test + @@ -161,12 +167,15 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + @@ -223,11 +232,14 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + \ No newline at end of file diff --git a/projects/visual-studio/test-16.vcxproj b/projects/visual-studio/test-16.vcxproj index 903d67e..6bc77e2 100644 --- a/projects/visual-studio/test-16.vcxproj +++ b/projects/visual-studio/test-16.vcxproj @@ -21,6 +21,7 @@ + @@ -37,6 +38,7 @@ + @@ -49,10 +51,11 @@ + - + @@ -74,9 +77,10 @@ - + + diff --git a/projects/visual-studio/test-16.vcxproj.filters b/projects/visual-studio/test-16.vcxproj.filters index cbaf6b5..84a4dec 100644 --- a/projects/visual-studio/test-16.vcxproj.filters +++ b/projects/visual-studio/test-16.vcxproj.filters @@ -90,6 +90,12 @@ test + + test\shared + + + test + @@ -164,12 +170,15 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + @@ -226,11 +235,14 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + \ No newline at end of file diff --git a/projects/visual-studio/test-clang.vcxproj b/projects/visual-studio/test-clang.vcxproj index 7694792..a2a5e1e 100644 --- a/projects/visual-studio/test-clang.vcxproj +++ b/projects/visual-studio/test-clang.vcxproj @@ -21,6 +21,7 @@ + @@ -37,6 +38,7 @@ + @@ -49,10 +51,11 @@ + - + @@ -74,9 +77,10 @@ - + + diff --git a/projects/visual-studio/test-clang.vcxproj.filters b/projects/visual-studio/test-clang.vcxproj.filters index 6e9c88a..d0dc72b 100644 --- a/projects/visual-studio/test-clang.vcxproj.filters +++ b/projects/visual-studio/test-clang.vcxproj.filters @@ -90,6 +90,12 @@ test + + test\shared + + + test + @@ -164,12 +170,15 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + @@ -226,11 +235,14 @@ hfsm\detail\root - - hfsm\detail\root - hfsm\detail + + hfsm\detail\shared + + + hfsm\detail\root + \ No newline at end of file diff --git a/test/shared/test_bit_array.cpp b/test/shared/test_bit_array.cpp index 1c12605..69630f9 100644 --- a/test/shared/test_bit_array.cpp +++ b/test/shared/test_bit_array.cpp @@ -5,7 +5,7 @@ namespace test_bit_array { //////////////////////////////////////////////////////////////////////////////// using BitArray = hfsm2::detail::BitArray; -using Bits = typename BitArray::Bits; +using Bits = typename BitArray::Bits; TEST_CASE("Shared.BitArray<>", "[shared]") { BitArray bitArray; diff --git a/test/shared/test_bit_stream.cpp b/test/shared/test_bit_stream.cpp new file mode 100644 index 0000000..667f00f --- /dev/null +++ b/test/shared/test_bit_stream.cpp @@ -0,0 +1,35 @@ +#include "../shared.hpp" + +namespace test_bit_stream { + +//////////////////////////////////////////////////////////////////////////////// + +using WriteStream = hfsm2::detail::BitWriteStream<46>; +using ReadStream = hfsm2::detail::BitReadStream <46>; +using StreamBuffer = typename WriteStream::Buffer; + +//------------------------------------------------------------------------------ + +TEST_CASE("Shared.BitStream<>", "[shared]") { + StreamBuffer buffer; + + WriteStream writeStream{buffer}; + writeStream.write< 5>((uint8_t) 27); + writeStream.write< 4>((uint8_t) 11); + writeStream.write< 3>((uint8_t) 5); + writeStream.write<12>((uint16_t) 1472); + writeStream.write<21>((uint32_t) 1000000); + REQUIRE(buffer.bitSize == 45); + + ReadStream readStream{buffer}; + REQUIRE(readStream.read< 5>() == 27); + REQUIRE(readStream.read< 4>() == 11); + REQUIRE(readStream.read< 3>() == 5); + REQUIRE(readStream.read<12>() == 1472); + REQUIRE(readStream.read<21>() == 1000000); + REQUIRE(readStream.cursor() == 45); +} + +//////////////////////////////////////////////////////////////////////////////// + +} diff --git a/test/test_replication.cpp b/test/test_replication.cpp index 046b227..b06dec6 100644 --- a/test/test_replication.cpp +++ b/test/test_replication.cpp @@ -329,6 +329,18 @@ TEST_CASE("FSM.Replication", "[machine]") { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + replicated.reset(); + { + assertActive(replicated, client::all, { + client::FSM::stateId(), + client::FSM::stateId(), + }); + + assertResumable(replicated, client::all, {}); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + authority.changeTo(); authority.update(); REQUIRE(authority.transitionHistory().count() == 0); diff --git a/test/test_serialization.cpp b/test/test_serialization.cpp new file mode 100644 index 0000000..8b30eb9 --- /dev/null +++ b/test/test_serialization.cpp @@ -0,0 +1,315 @@ +#define HFSM_ENABLE_SERIALIZATION +#define HFSM_ENABLE_VERBOSE_DEBUG_LOG +#include "shared.hpp" + +namespace test_serialization { + +//------------------------------------------------------------------------------ + +using M = hfsm2::Machine; + +//////////////////////////////////////////////////////////////////////////////// + +namespace server{ + +#define S(s) struct s + +using FSM = M::PeerRoot< + M::Composite + >, + M::Orthogonal, + M::Composite + > + >; + +#undef S + +//------------------------------------------------------------------------------ + +static_assert(FSM::regionId() == 1, ""); +static_assert(FSM::regionId() == 2, ""); +static_assert(FSM::regionId() == 3, ""); +static_assert(FSM::regionId() == 4, ""); +static_assert(FSM::regionId() == 5, ""); + +static_assert(FSM::stateId() == 1, ""); +static_assert(FSM::stateId() == 2, ""); +static_assert(FSM::stateId() == 3, ""); +static_assert(FSM::stateId() == 4, ""); +static_assert(FSM::stateId() == 5, ""); +static_assert(FSM::stateId() == 6, ""); +static_assert(FSM::stateId() == 7, ""); +static_assert(FSM::stateId() == 8, ""); +static_assert(FSM::stateId() == 9, ""); +static_assert(FSM::stateId() == 10, ""); +static_assert(FSM::stateId() == 11, ""); +static_assert(FSM::stateId() == 12, ""); + +//------------------------------------------------------------------------------ + +struct C1 : FSM::State {}; +struct C1_S1 : FSM::State {}; +struct C1_C2 : FSM::State {}; +struct C1_C2_S1 : FSM::State {}; +struct C1_C2_S2 : FSM::State {}; +struct O2 : FSM::State {}; +struct O2_C1 : FSM::State {}; +struct O2_C1_S1 : FSM::State {}; +struct O2_C1_S2 : FSM::State {}; +struct O2_C2 : FSM::State {}; +struct O2_C2_S1 : FSM::State {}; +struct O2_C2_S2 : FSM::State {}; + +//------------------------------------------------------------------------------ + +static_assert(FSM::Instance::STATE_COUNT == 13, ""); +static_assert(FSM::Instance::COMPO_REGIONS == 5, ""); +static_assert(FSM::Instance::COMPO_PRONGS == 10, ""); +static_assert(FSM::Instance::ORTHO_REGIONS == 1, ""); +static_assert(FSM::Instance::ORTHO_UNITS == 1, ""); +static_assert(FSM::Instance::ACTIVE_BITS == 3, ""); +static_assert(FSM::Instance::RESUMABLE_BITS == 10, ""); + +//------------------------------------------------------------------------------ + +const Types all = { + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), +}; + +} + +//////////////////////////////////////////////////////////////////////////////// + +namespace client { + +#define S(s) struct s + +using FSM = M::PeerRoot< + M::Composite + >, + M::Orthogonal, + M::Composite + > + >; + +#undef S + +//------------------------------------------------------------------------------ + +static_assert(FSM::regionId() == 1, ""); +static_assert(FSM::regionId() == 2, ""); +static_assert(FSM::regionId() == 3, ""); +static_assert(FSM::regionId() == 4, ""); +static_assert(FSM::regionId() == 5, ""); + +static_assert(FSM::stateId() == 1, ""); +static_assert(FSM::stateId() == 2, ""); +static_assert(FSM::stateId() == 3, ""); +static_assert(FSM::stateId() == 4, ""); +static_assert(FSM::stateId() == 5, ""); +static_assert(FSM::stateId() == 6, ""); +static_assert(FSM::stateId() == 7, ""); +static_assert(FSM::stateId() == 8, ""); +static_assert(FSM::stateId() == 9, ""); +static_assert(FSM::stateId() == 10, ""); +static_assert(FSM::stateId() == 11, ""); +static_assert(FSM::stateId() == 12, ""); + +//------------------------------------------------------------------------------ + +struct C1 : FSM::State {}; +struct C1_S1 : FSM::State {}; +struct C1_C2 : FSM::State {}; +struct C1_C2_S1 : FSM::State {}; +struct C1_C2_S2 : FSM::State {}; +struct O2 : FSM::State {}; +struct O2_C1 : FSM::State {}; +struct O2_C1_S1 : FSM::State {}; +struct O2_C1_S2 : FSM::State {}; +struct O2_C2 : FSM::State {}; +struct O2_C2_S1 : FSM::State {}; +struct O2_C2_S2 : FSM::State {}; + +//------------------------------------------------------------------------------ + +static_assert(FSM::Instance::STATE_COUNT == 13, ""); +static_assert(FSM::Instance::COMPO_REGIONS == 5, ""); +static_assert(FSM::Instance::COMPO_PRONGS == 10, ""); +static_assert(FSM::Instance::ORTHO_REGIONS == 1, ""); +static_assert(FSM::Instance::ORTHO_UNITS == 1, ""); +static_assert(FSM::Instance::ACTIVE_BITS == 3, ""); +static_assert(FSM::Instance::RESUMABLE_BITS == 10, ""); + +//------------------------------------------------------------------------------ + +const Types all = { + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), + FSM::stateId(), +}; + +} + +//------------------------------------------------------------------------------ + +static_assert(server::FSM::Instance::STATE_COUNT == client::FSM::Instance::STATE_COUNT , ""); +static_assert(server::FSM::Instance::COMPO_REGIONS == client::FSM::Instance::COMPO_REGIONS , ""); +static_assert(server::FSM::Instance::COMPO_PRONGS == client::FSM::Instance::COMPO_PRONGS , ""); +static_assert(server::FSM::Instance::ORTHO_REGIONS == client::FSM::Instance::ORTHO_REGIONS , ""); +static_assert(server::FSM::Instance::ORTHO_UNITS == client::FSM::Instance::ORTHO_UNITS , ""); +static_assert(server::FSM::Instance::ACTIVE_BITS == client::FSM::Instance::ACTIVE_BITS , ""); +static_assert(server::FSM::Instance::RESUMABLE_BITS == client::FSM::Instance::RESUMABLE_BITS, ""); + +//////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("FSM.Serialization", "[machine]") { + Logger logger; + + server::FSM::Instance::SerialBuffer buffer; + + { + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + server::FSM::Instance authority; + client::FSM::Instance replicated{&logger}; + { + logger.assertSequence({ + { hfsm2::StateID{0}, Event::ENTRY_GUARD }, + { client::FSM::stateId(), Event::ENTRY_GUARD }, + { client::FSM::stateId(), Event::ENTRY_GUARD }, + + { hfsm2::StateID{0}, Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + + { hfsm2::StateID{0}, Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + }); + + assertActive(authority, server::all, { + server::FSM::stateId(), + server::FSM::stateId(), + }); + + assertActive(replicated, client::all, { + client::FSM::stateId(), + client::FSM::stateId(), + }); + + assertResumable(authority, server::all, {}); + + assertResumable(replicated, client::all, {}); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + authority.changeTo(); + authority.update(); + { + assertActive(authority, server::all, { + server::FSM::stateId(), + server::FSM::stateId(), + server::FSM::stateId(), + server::FSM::stateId(), + server::FSM::stateId(), + }); + + assertResumable(authority, server::all, { + server::FSM::stateId(), + server::FSM::stateId(), + }); + } + authority.save(buffer); + + replicated.load(buffer); + { + logger.assertSequence({ + { client::FSM::stateId(), Event::EXIT }, + { client::FSM::stateId(), Event::EXIT }, + { hfsm2::StateID{0}, Event::EXIT }, + + { client::FSM::stateId(), Event::DESTRUCT }, + { client::FSM::stateId(), Event::DESTRUCT }, + { hfsm2::StateID{0}, Event::DESTRUCT }, + + { hfsm2::StateID{0}, Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + { client::FSM::stateId(), Event::CONSTRUCT }, + + { hfsm2::StateID{0}, Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + { client::FSM::stateId(), Event::ENTER }, + }); + + assertActive(replicated, client::all, { + client::FSM::stateId(), + client::FSM::stateId(), + client::FSM::stateId(), + client::FSM::stateId(), + client::FSM::stateId(), + }); + + assertResumable(replicated, client::all, { + client::FSM::stateId(), + client::FSM::stateId(), + }); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + } +} + +//////////////////////////////////////////////////////////////////////////////// + +}