/** * @file * @author 2017 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) * @copyright Simplified BSD * * @cond * This program is free software: you can redistribute it and/or modify * it under the terms of the FreeBSD license as published by the FreeBSD * project. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the FreeBSD license along with this * program. If not, see . * @endcond */ //#define USCXML_VERBOSE #ifndef LARGEMICROSTEP_H_2573547 #define LARGEMICROSTEP_H_2573547 #include "uscxml/Common.h" #include "uscxml/util/DOM.h" // X #include "uscxml/util/Predicates.h" #include "uscxml/util/String.h" #include "uscxml/interpreter/InterpreterMonitor.h" #include #include #include #include #include #include "MicroStepImpl.h" #ifdef _WIN32 #define BITSET_BLOCKTYPE size_t #else #define BITSET_BLOCKTYPE #endif namespace uscxml { /** * @ingroup microstep * @ingroup impl * * MicroStep implementation with a more economic growth of data-structures for large state-charts. */ class LargeMicroStep : public MicroStepImpl { public: LargeMicroStep(MicroStepCallbacks* callbacks); virtual ~LargeMicroStep(); virtual std::shared_ptr create(MicroStepCallbacks* callbacks); std::string getName() { return "large"; } virtual InterpreterState step(size_t blockMs); virtual void reset(); virtual bool isInState(const std::string& stateId); virtual std::list getConfiguration(); void markAsCancelled(); virtual void deserialize(const Data& encodedState) {} virtual Data serialize() { return Data(); } protected: LargeMicroStep() {} // only for the factory class State; class Transition; struct StateOrder { bool operator()(const State* lhs, const State* rhs) const { return lhs->documentOrder < rhs->documentOrder; } }; struct StateOrderPostFix { bool operator()(const State* lhs, const State* rhs) const { return lhs->postFixOrder < rhs->postFixOrder; } }; struct TransitionOrder { bool operator()(const Transition* lhs, const Transition* rhs) const { return lhs->postFixOrder < rhs->postFixOrder; } }; std::vector _states; ///< States in document order std::vector _transitions; ///< Transitions in reverse post-order boost::container::flat_set _configuration; boost::container::flat_set _configurationPostFix; boost::container::flat_set _invocations; boost::container::flat_set _history; boost::container::flat_set _initializedData; class Transition { public: Transition(uint32_t postFixOrder) : postFixOrder(postFixOrder) {} const uint32_t postFixOrder; // making these const increases performance somewhat XERCESC_NS::DOMElement* element = NULL; boost::container::flat_set compatible; boost::container::flat_set conflicting; std::pair exitSet; State* source = NULL; std::vector target; XERCESC_NS::DOMElement* onTrans = NULL; std::string event; std::string cond; unsigned char type = 0; }; class State { public: State(uint32_t documentOrder) : documentOrder(documentOrder) {} const uint32_t documentOrder; uint32_t postFixOrder; XERCESC_NS::DOMElement* element; boost::container::flat_set completion; boost::container::flat_set ancestors; // TODO: leverage! std::vector children; State* parent = NULL; std::vector transitions; std::vector data; std::vector invoke; std::vector onEntry; std::vector onExit; XERCESC_NS::DOMElement* doneData = NULL; std::string name; unsigned char type; }; void init(XERCESC_NS::DOMElement* scxml); std::list getCompletion(const XERCESC_NS::DOMElement* state); std::list getHistoryCompletion(const XERCESC_NS::DOMElement* history); unsigned char _flags = 0; boost::container::flat_set > _microstepConfigurations; bool _isInitialized = false; bool _isCancelled = false; Event _event; // we do not care about the event's representation std::list _globalScripts; Binding _binding; XERCESC_NS::DOMElement* _scxml; X _xmlPrefix; X _xmlNS; /// Normalize order of elements per state void resortStates(XERCESC_NS::DOMElement* node, const X& xmlPrefix); private: boost::container::flat_set _exitSet; boost::container::flat_set _entrySet; boost::container::flat_set _targetSet; boost::container::flat_set _tmpStates; boost::dynamic_bitset _compatible; boost::dynamic_bitset _conflicting; boost::container::flat_set _transSet; // adapted from http://www.cplusplus.com/reference/algorithm/set_intersection/ template bool intersects(iter_t1 first1, iter_t1 last1, iter_t2 first2, iter_t2 last2) { while (first1 != last1 && first2 != last2) { if (compare()(*first1, *first2)) { ++first1; } else if (compare()(*first2, *first1)) { ++first2; } else { return true; } } return false; } bool isInFinal(const State* state); void printStateNames(const boost::container::flat_set& a); uint32_t getTransitionDomain(const Transition* transition); std::pair getExitSet(const Transition* transition); std::map > _exitSetCache; friend class Factory; }; } #endif /* end of include guard: LARGEMICROSTEP_H_2573547 */