diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-06-27 11:11:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-27 11:11:13 (GMT) |
commit | e24393f41834f116038faf6c6d5012575a67136a (patch) | |
tree | a1e83679e55781bc92849a07c5acda7b5c09908c /src/uscxml/interpreter/LargeMicroStep.h | |
parent | b3a2d91805feb81f79ee52c30a077521912b0bf9 (diff) | |
parent | 3a5692f40663282640775f8ff497c4860d265a2a (diff) | |
download | uscxml-e24393f41834f116038faf6c6d5012575a67136a.zip uscxml-e24393f41834f116038faf6c6d5012575a67136a.tar.gz uscxml-e24393f41834f116038faf6c6d5012575a67136a.tar.bz2 |
Merge pull request #149 from tklab-tud/sradomski
remerge
Diffstat (limited to 'src/uscxml/interpreter/LargeMicroStep.h')
-rw-r--r-- | src/uscxml/interpreter/LargeMicroStep.h | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/uscxml/interpreter/LargeMicroStep.h b/src/uscxml/interpreter/LargeMicroStep.h new file mode 100644 index 0000000..3443d80 --- /dev/null +++ b/src/uscxml/interpreter/LargeMicroStep.h @@ -0,0 +1,179 @@ +/** + * @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 <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +//#define USCXML_VERBOSE + +#ifndef LARGEMICROSTEP_H_2573547 +#define LARGEMICROSTEP_H_2573547 + +#include "uscxml/config.h" +#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" + +/* flat_set is 10 times faster than std::set here */ +#include <boost/container/flat_set.hpp> + +#include <vector> +#include <list> +#include <map> +#include "MicroStepImpl.h" + +namespace uscxml { + +/** + * @ingroup microstep + * @ingroup impl + */ +class LargeMicroStep : public MicroStepImpl { +public: + + LargeMicroStep(MicroStepCallbacks* callbacks); + virtual ~LargeMicroStep(); + virtual std::shared_ptr<MicroStepImpl> create(MicroStepCallbacks* callbacks); + + virtual InterpreterState step(size_t blockMs); + virtual void reset(); + virtual bool isInState(const std::string& stateId); + virtual std::list<XERCESC_NS::DOMElement*> getConfiguration(); + void markAsCancelled(); + + virtual void deserialize(const Data& encodedState) {} + virtual Data serialize() { return Data(); } + +protected: + class State; + class Transition; + + struct StateOrder + { + bool operator()(const State* lhs, const State* rhs) const { return lhs->documentOrder < rhs->documentOrder; } + }; + + struct TransitionOrder + { + bool operator()(const Transition* lhs, const Transition* rhs) const { return lhs->postFixOrder < rhs->postFixOrder; } + }; + + std::vector<State*> _states; ///< States in document order + std::vector<Transition*> _transitions; ///< Transitions in reverse post-order + + boost::container::flat_set<State*, StateOrder> _configuration; + boost::container::flat_set<State*, StateOrder> _invocations; + boost::container::flat_set<State*, StateOrder> _history; + boost::container::flat_set<State*, StateOrder> _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<Transition*, TransitionOrder> compatible; + boost::container::flat_set<State*, StateOrder> exitSet; + + State* source = NULL; + std::vector<State*> 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; + + XERCESC_NS::DOMElement* element; + boost::container::flat_set<State*, StateOrder> completion; + std::vector<State*> children; + State* parent = NULL; + + std::vector<Transition*> transitions; + std::vector<XERCESC_NS::DOMElement*> data; + std::vector<XERCESC_NS::DOMElement*> invoke; + std::vector<XERCESC_NS::DOMElement*> onEntry; + std::vector<XERCESC_NS::DOMElement*> onExit; + XERCESC_NS::DOMElement* doneData = NULL; + + unsigned char type; + }; + + void init(XERCESC_NS::DOMElement* scxml); + + std::list<XERCESC_NS::DOMElement*> getCompletion(const XERCESC_NS::DOMElement* state); + std::list<XERCESC_NS::DOMElement*> getHistoryCompletion(const XERCESC_NS::DOMElement* history); + + unsigned char _flags = 0; + boost::container::flat_set<boost::container::flat_set<State*, StateOrder> > _microstepConfigurations; + + bool _isInitialized = false; + bool _isCancelled = false; + Event _event; // we do not care about the event's representation + + std::list<XERCESC_NS::DOMElement*> _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<State*, StateOrder> _exitSet; + boost::container::flat_set<State*, StateOrder> _entrySet; + boost::container::flat_set<State*, StateOrder> _targetSet; + boost::container::flat_set<State*, StateOrder> _tmpStates; + + boost::container::flat_set<Transition*, TransitionOrder> _compatible; + boost::container::flat_set<Transition*, TransitionOrder> _transSet; + + // adapted from http://www.cplusplus.com/reference/algorithm/set_intersection/ + template <class iter_t1, class iter_t2, class compare = StateOrder> + 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<LargeMicroStep::State*, LargeMicroStep::StateOrder>& a); + +}; + +} +#endif /* end of include guard: LARGEMICROSTEP_H_2573547 */ |