summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-07-10 15:13:06 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-07-10 15:13:06 (GMT)
commit286f8d747d198a66b81396ba8197b101ae2d59ed (patch)
tree2ad222fdbcb2ba6f7ead0ca41e5a6d98ae4c4287
parent799a95c560338643894ffd80510db8b48baa2f45 (diff)
downloaduscxml-286f8d747d198a66b81396ba8197b101ae2d59ed.zip
uscxml-286f8d747d198a66b81396ba8197b101ae2d59ed.tar.gz
uscxml-286f8d747d198a66b81396ba8197b101ae2d59ed.tar.bz2
More performance for microsteppers
-rw-r--r--src/uscxml/interpreter/FastMicroStep.cpp263
-rw-r--r--src/uscxml/interpreter/FastMicroStep.h43
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.cpp11
-rw-r--r--src/uscxml/interpreter/LargeMicroStep.cpp70
-rw-r--r--src/uscxml/interpreter/LargeMicroStep.h8
-rw-r--r--src/uscxml/util/Convenience.cpp5
-rw-r--r--src/uscxml/util/DOM.h6
-rw-r--r--src/uscxml/util/Predicates.cpp16
-rw-r--r--test/src/test-lifecycle.cpp36
-rw-r--r--test/src/test-serialization.cpp5
-rw-r--r--test/src/test-stress.cpp2
-rw-r--r--test/src/test-validating.cpp2
12 files changed, 315 insertions, 152 deletions
diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp
index d6ad298..1345403 100644
--- a/src/uscxml/interpreter/FastMicroStep.cpp
+++ b/src/uscxml/interpreter/FastMicroStep.cpp
@@ -17,8 +17,6 @@
* @endcond
*/
-#undef USCXML_VERBOSE
-//#undef WITH_CACHE_FILES
#include "uscxml/config.h"
#include "FastMicroStep.h"
@@ -31,6 +29,12 @@
#include "uscxml/interpreter/Logging.h"
+#include <stdlib.h> // strtol
+#include <iostream>
+
+#undef USCXML_VERBOSE
+#undef WITH_CACHE_FILES
+
#define BIT_ANY_SET(b) (!b.none())
#define BIT_HAS(idx, bitset) (bitset[idx])
#define BIT_HAS_AND(bitset1, bitset2) bitset1.intersects(bitset2)
@@ -201,33 +205,89 @@ void FastMicroStep::resortStates(DOMElement* element, const X& xmlPrefix) {
}
}
-std::list<XERCESC_NS::DOMElement*> FastMicroStep::getExitSetCached(const XERCESC_NS::DOMElement* transition,
- const XERCESC_NS::DOMElement* root) {
+std::pair<uint32_t, uint32_t> FastMicroStep::getExitSet(const Transition* transition) {
+ if (_exitSetCache.find(transition->postFixOrder) == _exitSetCache.end()) {
+ std::pair<uint32_t, uint32_t> statesToExit;
+ uint32_t domain = getTransitionDomain(transition);
+ if (domain == std::numeric_limits<uint32_t>::max())
+ return statesToExit;
+
+ State* domainState = _states[domain];
+
+ // start of exit set
+ statesToExit.first = domainState->documentOrder + 1; // do not include domain itself
+
+ // end of exit set
+ XERCESC_NS::DOMElement* sibling = domainState->element->getNextElementSibling();
+ while(sibling && !isState(sibling))
+ sibling = sibling->getNextElementSibling();
+ if (sibling) {
+ State* siblingState = (State*)sibling->getUserData(X("uscxmlState"));
+ statesToExit.second = siblingState->documentOrder - 1;
+ } else {
+ statesToExit.second = _states.size() - 1;
+ }
+ _exitSetCache[transition->postFixOrder] = statesToExit;
+ return statesToExit;
+ }
+ return _exitSetCache[transition->postFixOrder];
+}
+
+uint32_t FastMicroStep::getTransitionDomain(const Transition* transition) {
+ size_t i, j;
+ if (!transition->target.any())
+ return std::numeric_limits<uint32_t>::max();
+
+ bool internal = (HAS_ATTR(transition->element, kXMLCharType) ? ATTR(transition->element, kXMLCharType) == "internal" : false);
+ if (internal && USCXML_STATE_MASK(_states[transition->source]->type) == USCXML_STATE_COMPOUND) {
+ i = transition->target.find_first();
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
+ if(!(_states[i]->ancestors[transition->source])) {
+ goto BREAK_LOOP;
+ }
+ i = transition->target.find_next(i);
- if (_cache.exitSet.find(transition) == _cache.exitSet.end()) {
- _cache.exitSet[transition] = getExitSet(transition, root);
+ }
+ return _states[transition->source]->documentOrder;
}
+BREAK_LOOP:
- return _cache.exitSet[transition];
-}
+ // find LCCA
+ uint32_t ancestor = std::numeric_limits<uint32_t>::max();
-bool FastMicroStep::conflictsCached(const DOMElement* t1, const DOMElement* t2, const DOMElement* root) {
- if (getSourceState(t1) == getSourceState(t2))
- return true;
+ // reverse walk up!
+ i = _states[transition->source]->parent;
+ State* anc = _states[i];
- if (DOMUtils::isDescendant(getSourceState(t1), getSourceState(t2)))
- return true;
+ while(anc) {
+ if (USCXML_STATE_MASK(anc->type) != USCXML_STATE_COMPOUND) {
+ // LCCA has to be a compound
+ anc = _states[anc->parent];
+ continue;
+ }
- if (DOMUtils::isDescendant(getSourceState(t2), getSourceState(t1)))
- return true;
+ j = transition->target.find_first();
+ while(j != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
+ if (!(_states[j]->ancestors[anc->documentOrder])) {
+ goto NEXT_ANCESTOR;
+ }
+ j = transition->target.find_next(j);
+ }
- if (DOMUtils::hasIntersection(getExitSetCached(t1, root), getExitSetCached(t2, root)))
- return true;
+ ancestor = anc->documentOrder;
+ break;
+NEXT_ANCESTOR:
+ anc = _states[anc->parent];
+ if (anc->documentOrder == 0)
+ break;
+ }
- return false;
+ // none found - take uppermost root as ancestor
+ if (ancestor == std::numeric_limits<uint32_t>::max())
+ return 0;
+ return ancestor;
}
-
void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
_scxml = scxml;
@@ -266,8 +326,7 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
_invocations.resize(tmp.size());
for (i = 0; i < _states.size(); i++) {
- _states[i] = new State();
- _states[i]->documentOrder = i;
+ _states[i] = new State(i);
_states[i]->element = tmp.front();
if (HAS_ATTR(_states[i]->element, kXMLCharId)) {
_states[i]->name = ATTR(_states[i]->element, kXMLCharId);
@@ -391,12 +450,24 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
cachedState->compound["completion"] = Data(toBase64(_states[i]->completion));
COMPLETION_STABLISHED:
#endif
+
+
+#ifdef WITH_CACHE_FILES
+ if (withCache && cachedState->compound.find("hasHistoryChild") != cachedState->compound.end()) {
+ _states[i]->element->setUserData(X("hasHistoryChild"), _states[strTo<uint32_t>(cachedState->compound["hasHistoryChild"])], NULL);
+ }
+#endif
+
// this is set when establishing the completion
if (_states[i]->element->getUserData(X("hasHistoryChild")) == _states[i]) {
_states[i]->type |= USCXML_STATE_HAS_HISTORY;
+#ifdef WITH_CACHE_FILES
+ if (withCache)
+ cachedState->compound["hasHistoryChild"] = Data(((State*)_states[i]->element->getUserData(X("hasHistoryChild")))->documentOrder);
+#endif
}
- // establish the states' ancestors
+ // parent relation
DOMNode* parent = _states[i]->element->getParentNode();
if (parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) {
State* uscxmlState = (State*)parent->getUserData(X("uscxmlState"));
@@ -406,6 +477,7 @@ COMPLETION_STABLISHED:
}
}
+ // establish the states' ancestors
while(parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) {
State* uscxmlState = (State*)parent->getUserData(X("uscxmlState"));
@@ -436,12 +508,12 @@ COMPLETION_STABLISHED:
tmp = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "transition", tmp);
_transitions.resize(tmp.size());
+ _exitSets.resize(tmp.size());
for (i = 0; i < _transitions.size(); i++) {
- _transitions[i] = new Transition();
+ _transitions[i] = new Transition(i);
_transitions[i]->element = tmp.front();
_transitions[i]->conflicts.resize(_transitions.size());
- _transitions[i]->exitSet.resize(_states.size());
_transitions[i]->target.resize(_states.size());
tmp.pop_front();
}
@@ -467,69 +539,6 @@ COMPLETION_STABLISHED:
}
#endif
- // establish the transitions' exit set
- assert(_transitions[i]->element != NULL);
-
-#ifdef WITH_CACHE_FILES
- if (withCache && cachedTrans->compound.find("exitset") != cachedTrans->compound.end()) {
- boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet = fromBase64(cachedTrans->compound["exitset"]);
- if (exitSet.size() != _states.size()) {
- LOG(_callbacks->getLogger(), USCXML_WARN) << "Transition exit set has wrong size: Cache corrupted" << std::endl;
- } else {
- _transitions[i]->exitSet = exitSet;
- goto EXIT_SET_ESTABLISHED;
- }
- }
-#endif
- {
- std::list<DOMElement*> exitList = getExitSetCached(_transitions[i]->element, _scxml);
-
- for (j = 0; j < _states.size(); j++) {
- if (!exitList.empty() && _states[j]->element == exitList.front()) {
- _transitions[i]->exitSet[j] = true;
- exitList.pop_front();
- } else {
- _transitions[i]->exitSet[j] = false;
- }
- }
- assert(exitList.size() == 0);
- }
-#ifdef WITH_CACHE_FILES
- if (withCache)
- cachedTrans->compound["exitset"] = Data(toBase64(_transitions[i]->exitSet));
-EXIT_SET_ESTABLISHED:
-#endif
-
- // establish the transitions' conflict set
-#ifdef WITH_CACHE_FILES
- if (withCache && cachedTrans->compound.find("conflicts") != cachedTrans->compound.end()) {
- boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts = fromBase64(cachedTrans->compound["conflicts"]);
- if (conflicts.size() != _transitions.size()) {
- LOG(_callbacks->getLogger(), USCXML_WARN) << "Transition conflicts has wrong size: Cache corrupted" << std::endl;
- } else {
- _transitions[i]->conflicts = conflicts;
- goto CONFLICTS_ESTABLISHED;
- }
- }
-#endif
- for (j = i; j < _transitions.size(); j++) {
- if (conflictsCached(_transitions[i]->element, _transitions[j]->element, _scxml)) {
- _transitions[i]->conflicts[j] = true;
- } else {
- _transitions[i]->conflicts[j] = false;
- }
- // std::cout << ".";
- }
-
- // conflicts matrix is symmetric
- for (j = 0; j < i; j++) {
- _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
- }
-#ifdef WITH_CACHE_FILES
- if (withCache)
- cachedTrans->compound["conflicts"] = Data(toBase64(_transitions[i]->conflicts));
-CONFLICTS_ESTABLISHED:
-#endif
// establish the transitions' target set
#ifdef WITH_CACHE_FILES
if (withCache && cachedTrans->compound.find("target") != cachedTrans->compound.end()) {
@@ -591,8 +600,80 @@ TARGET_SET_ESTABLISHED:
if (_transitions[i]->element->getChildElementCount() > 0) {
_transitions[i]->onTrans = _transitions[i]->element;
}
+
+ // establish the transitions' exit set
+ assert(_transitions[i]->element != NULL);
+
+ {
+ _exitSets[i] = getExitSet(_transitions[i]);
+ }
+
+ }
+
+ /**
+ * This bound by cache locality!
+ * Before you change anything, do benchmark!
+ */
+
+#define anc1 _states[_transitions[i]->source]->ancestors
+#define exit1 _exitSets[i]
+#define exit2 _exitSets[j]
+
+ for (i = 0; i < _transitions.size(); i++) {
+ anc1 = _states[_transitions[i]->source]->ancestors;
+ const uint32_t source1 = _transitions[i]->source;
+
+ for (j = i + 1; j < _transitions.size(); j++) {
+
+ if (exit1.first == 0 && exit2.first == 0) {
+ goto COMPATIBLE_TRANS;
+ }
+
+ if (exit1.first <= exit2.first && exit1.second >= exit2.first) {
+ goto CONFLICTING_TRANS;
+ }
+
+ if (exit2.first <= exit1.first && exit2.second >= exit1.first) {
+ goto CONFLICTING_TRANS;
+ }
+
+COMPATIBLE_TRANS:
+ if (_transitions[j]->source == source1) {
+ goto CONFLICTING_TRANS;
+ }
+
+ if (anc1[_transitions[j]->source]) {
+ goto CONFLICTING_TRANS;
+ }
+
+ if (_states[_transitions[j]->source]->ancestors[source1]) {
+ goto CONFLICTING_TRANS;
+ }
+
+ _transitions[i]->conflicts[j] = false;
+// _transitions[j]->conflicts[i] = false;
+ continue;
+CONFLICTING_TRANS:
+ _transitions[i]->conflicts[j] = true;
+// _transitions[j]->conflicts[i] = true;
+
+ continue;
+
+ }
+#if 0 // moved down for cache locality
+ // conflicts matrix is symmetric
+ for (j = 0; j < i; j++) {
+ _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
+ }
+#endif
+ }
+
+ for (i = 0; i < _transitions.size(); i++) {
+ // conflicts matrix is symmetric
+ for (j = 0; j < i; j++) {
+ _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
+ }
}
- _cache.exitSet.clear();
// initialize bitarrays for step()
_exitSet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false);
@@ -809,7 +890,11 @@ SELECT_TRANSITIONS:
_targetSet |= USCXML_GET_TRANS(i).target;
/* states that will be left */
- _exitSet |= USCXML_GET_TRANS(i).exitSet;
+ for (auto documentOrder = _exitSets[i].first;
+ documentOrder <= _exitSets[i].second;
+ documentOrder++) {
+ _exitSet[documentOrder] = true;
+ }
BIT_SET_AT(i, _transSet);
}
diff --git a/src/uscxml/interpreter/FastMicroStep.h b/src/uscxml/interpreter/FastMicroStep.h
index 5ff1117..543d6a9 100644
--- a/src/uscxml/interpreter/FastMicroStep.h
+++ b/src/uscxml/interpreter/FastMicroStep.h
@@ -72,48 +72,43 @@ protected:
class Transition {
public:
- Transition() : element(NULL), source(0), onTrans(NULL), type(0) {}
+ Transition(uint32_t postFixOrder) : postFixOrder(postFixOrder) {}
+ const uint32_t postFixOrder; // making these const increases performance somewhat
- XERCESC_NS::DOMElement* element;
+ XERCESC_NS::DOMElement* element = NULL;
boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts;
- boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet;
- uint32_t source;
+ uint32_t source = 0;
boost::dynamic_bitset<BITSET_BLOCKTYPE> target;
- XERCESC_NS::DOMElement* onTrans;
+ XERCESC_NS::DOMElement* onTrans = NULL;
std::string event;
std::string cond;
- unsigned char type;
+ unsigned char type = 0;
};
class State {
public:
- State() : element(NULL), parent(0), documentOrder(0), doneData(NULL), type(0) {}
+ State(uint32_t documentOrder) : documentOrder(documentOrder) {}
+ const uint32_t documentOrder;
- XERCESC_NS::DOMElement* element;
+ XERCESC_NS::DOMElement* element = NULL;
boost::dynamic_bitset<BITSET_BLOCKTYPE> completion;
boost::dynamic_bitset<BITSET_BLOCKTYPE> children;
boost::dynamic_bitset<BITSET_BLOCKTYPE> ancestors;
- uint32_t parent;
- uint32_t documentOrder;
+ uint32_t parent = 0;
std::list<XERCESC_NS::DOMElement*> data;
std::list<XERCESC_NS::DOMElement*> invoke;
std::list<XERCESC_NS::DOMElement*> onEntry;
std::list<XERCESC_NS::DOMElement*> onExit;
- XERCESC_NS::DOMElement* doneData;
+ XERCESC_NS::DOMElement* doneData = NULL;
std::string name;
- unsigned char type;
- };
-
- class CachedPredicates {
- public:
- std::map<const XERCESC_NS::DOMElement*, std::list<XERCESC_NS::DOMElement*> > exitSet;
+ unsigned char type = 0;
};
virtual void init(XERCESC_NS::DOMElement* scxml);
@@ -147,21 +142,17 @@ private:
std::list<XERCESC_NS::DOMElement*> getHistoryCompletion(const XERCESC_NS::DOMElement* state);
void resortStates(XERCESC_NS::DOMElement* node, const X& xmlPrefix);
- bool conflictsCached(const XERCESC_NS::DOMElement* t1, const XERCESC_NS::DOMElement* t2, const XERCESC_NS::DOMElement* root); ///< overrides implementation Predicates::conflicts for speed
-
std::string toBase64(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset);
boost::dynamic_bitset<BITSET_BLOCKTYPE> fromBase64(const std::string& encoded);
- std::list<XERCESC_NS::DOMElement*> getExitSetCached(const XERCESC_NS::DOMElement* transition,
- const XERCESC_NS::DOMElement* root);
-
- CachedPredicates _cache;
-
boost::dynamic_bitset<BITSET_BLOCKTYPE> _exitSet;
boost::dynamic_bitset<BITSET_BLOCKTYPE> _entrySet;
boost::dynamic_bitset<BITSET_BLOCKTYPE> _targetSet;
boost::dynamic_bitset<BITSET_BLOCKTYPE> _tmpStates;
+ // per transition exit set, kept in a vector for cache locality (~25% faster than transition[i]->exitSet)
+ std::vector<std::pair<uint32_t, uint32_t> > _exitSets;
+
boost::dynamic_bitset<BITSET_BLOCKTYPE> _conflicts;
boost::dynamic_bitset<BITSET_BLOCKTYPE> _transSet;
@@ -169,6 +160,10 @@ private:
void printStateNames(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset);
#endif
+ uint32_t getTransitionDomain(const Transition* transition);
+ std::pair<uint32_t, uint32_t> getExitSet(const Transition* transition);
+ std::map<uint32_t, std::pair<uint32_t, uint32_t> > _exitSetCache;
+
friend class Factory;
};
diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp
index 9e59cea..414dba2 100644
--- a/src/uscxml/interpreter/InterpreterImpl.cpp
+++ b/src/uscxml/interpreter/InterpreterImpl.cpp
@@ -340,6 +340,7 @@ void InterpreterImpl::init() {
std::ifstream dataFS(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache");
try {
if (dataFS.is_open()) {
+ LOGD(USCXML_INFO) << "Using cache from '" << sharedTemp << PATH_SEPERATOR << md5(_baseURL) << ".uscxml.cache'" << std::endl;
std::string cacheStr((std::istreambuf_iterator<char>(dataFS)),
std::istreambuf_iterator<char>());
_cache = Data::fromJSON(cacheStr);
@@ -349,9 +350,11 @@ void InterpreterImpl::init() {
}
// get md5 of current document
- std::stringstream ss;
- ss << *_document;
- _md5 = md5(ss.str());
+ if (_md5.length() == 0) {
+ std::stringstream ss;
+ ss << *_document;
+ _md5 = md5(ss.str());
+ }
if (_cache.compound.find("InterpreterImpl") != _cache.compound.end() &&
_cache.compound["InterpreterImpl"].compound.find("md5") != _cache.compound["InterpreterImpl"].compound.end() &&
@@ -390,7 +393,7 @@ void InterpreterImpl::init() {
}
if (!_microStepper) {
- _microStepper = MicroStep(std::shared_ptr<MicroStepImpl>(new FastMicroStep(this)));
+ _microStepper = MicroStep(std::shared_ptr<MicroStepImpl>(new LargeMicroStep(this)));
}
_microStepper.init(_scxml);
diff --git a/src/uscxml/interpreter/LargeMicroStep.cpp b/src/uscxml/interpreter/LargeMicroStep.cpp
index eab303c..a6d90f4 100644
--- a/src/uscxml/interpreter/LargeMicroStep.cpp
+++ b/src/uscxml/interpreter/LargeMicroStep.cpp
@@ -111,6 +111,71 @@ void LargeMicroStep::markAsCancelled() {
_isCancelled = true;
}
+void LargeMicroStep::deserialize(const Data& encodedState) {
+ if (!encodedState.hasKey("configuration") ||
+ !encodedState.hasKey("invocations") ||
+ !encodedState.hasKey("histories") ||
+ !encodedState.hasKey("intializedData")) {
+ ERROR_PLATFORM_THROW("Data does not contain required fields for deserialization ");
+ }
+
+ reset();
+
+ for (auto stateId : encodedState["configuration"].array) {
+ _configuration.insert(_states[strTo<uint32_t>(stateId.atom)]);
+ _configurationPostFix.insert(_states[strTo<uint32_t>(stateId.atom)]);
+ }
+
+ for (auto stateId : encodedState["invocations"].array) {
+ _invocations.insert(_states[strTo<uint32_t>(stateId.atom)]);
+ }
+
+ for (auto stateId : encodedState["histories"].array) {
+ _history.insert(_states[strTo<uint32_t>(stateId.atom)]);
+ }
+
+ for (auto stateId : encodedState["intializedData"].array) {
+ _initializedData.insert(_states[strTo<uint32_t>(stateId.atom)]);
+ }
+
+ for (auto invoked : _invocations) {
+ for (auto invoker : invoked->invoke) {
+ try {
+ _callbacks->invoke(invoker);
+ } catch (ErrorEvent e) {
+ LOG(_callbacks->getLogger(), USCXML_WARN) << e;
+ } catch (...) {
+ }
+ }
+ }
+
+ _flags |= USCXML_CTX_INITIALIZED;
+}
+
+Data LargeMicroStep::serialize() {
+ Data encodedState;
+
+ encodedState["configuration"] = Data();
+ encodedState["invocations"] = Data();
+ encodedState["histories"] = Data();
+ encodedState["intializedData"] = Data();
+
+ for (auto state : _configuration) {
+ encodedState["configuration"].array.push_back(Data(state->documentOrder));
+ }
+ for (auto state : _invocations) {
+ encodedState["invocations"].array.push_back(Data(state->documentOrder));
+ }
+ for (auto state : _history) {
+ encodedState["histories"].array.push_back(Data(state->documentOrder));
+ }
+ for (auto state : _initializedData) {
+ encodedState["intializedData"].array.push_back(Data(state->documentOrder));
+ }
+
+ return encodedState;
+}
+
void LargeMicroStep::reset() {
_isCancelled = false;
_flags = USCXML_CTX_PRISTINE;
@@ -453,6 +518,11 @@ void LargeMicroStep::init(XERCESC_NS::DOMElement* scxml) {
assert(transList.size() == 0);
}
+// for (i = 0; i < _transitions.size(); i++) {
+// _transitions[i]->exitSet = getExitSet(_transitions[i]);
+// LOGD(USCXML_DEBUG) << "" << _transitions[i]->exitSet.second << " / " << _transitions[i]->exitSet.first << std::endl;
+// }
+
_isInitialized = true;
}
diff --git a/src/uscxml/interpreter/LargeMicroStep.h b/src/uscxml/interpreter/LargeMicroStep.h
index 35e21de..72c2292 100644
--- a/src/uscxml/interpreter/LargeMicroStep.h
+++ b/src/uscxml/interpreter/LargeMicroStep.h
@@ -68,10 +68,8 @@ public:
virtual std::list<XERCESC_NS::DOMElement*> getConfiguration();
void markAsCancelled();
- virtual void deserialize(const Data& encodedState) {}
- virtual Data serialize() {
- return Data();
- }
+ virtual void deserialize(const Data& encodedState);
+ virtual Data serialize();
protected:
LargeMicroStep() {} // only for the factory
@@ -135,7 +133,7 @@ protected:
XERCESC_NS::DOMElement* element;
boost::container::flat_set<State*, StateOrder> completion;
- boost::container::flat_set<State*, StateOrder> ancestors; // TODO: leverage!
+ boost::container::flat_set<State*, StateOrder> ancestors; // TODO: change to indices
std::vector<State*> children;
State* parent = NULL;
diff --git a/src/uscxml/util/Convenience.cpp b/src/uscxml/util/Convenience.cpp
index 4f47449..4cfbb5e 100644
--- a/src/uscxml/util/Convenience.cpp
+++ b/src/uscxml/util/Convenience.cpp
@@ -61,6 +61,10 @@ bool isInteger(const char* pszInput, int nNumberBase) {
bool iequals(const std::string& a, const std::string& b) {
// this impementation beats boost::iequals 2700ms vs 2100ms for test-performance.scxml - we don't care for non-ascii yet
+#if 0
+ // not platform independent?
+ return strcasecmp(a.c_str(), b.c_str()) == 0;
+#else
unsigned int size = a.size();
if (b.size() != size)
return false;
@@ -68,6 +72,7 @@ bool iequals(const std::string& a, const std::string& b) {
if (tolower(a[i]) != tolower(b[i]))
return false;
return true;
+#endif
}
bool equals(const std::string& a, const std::string& b) {
diff --git a/src/uscxml/util/DOM.h b/src/uscxml/util/DOM.h
index 2adc675..1e0b8ce 100644
--- a/src/uscxml/util/DOM.h
+++ b/src/uscxml/util/DOM.h
@@ -201,6 +201,10 @@ public :
return _localForm;
}
+ int iequals(const XMLCh* const other) const {
+ return XERCESC_NS::XMLString::compareIString(_unicodeForm, other);
+ }
+
operator XMLCh* () const {
assert(_unicodeForm != NULL); // constructor with XMLCh
return _unicodeForm;
@@ -217,7 +221,7 @@ public :
}
bool operator==(const X& other) const {
- return (_unicodeForm == other._unicodeForm) != 0;
+ return (_localForm == other._localForm) != 0;
}
bool operator!=(const X& other) const {
diff --git a/src/uscxml/util/Predicates.cpp b/src/uscxml/util/Predicates.cpp
index 3f6128f..6649907 100644
--- a/src/uscxml/util/Predicates.cpp
+++ b/src/uscxml/util/Predicates.cpp
@@ -183,21 +183,23 @@ bool isState(const DOMElement* state, bool properOnly) {
if (!state)
return false;
- std::string localName = LOCALNAME(state);
- if (iequals("state", localName))
+ // comparison with XMLCh* is faster than transcoding each
+ const XMLCh* localname = state->getLocalName();
+
+ if (kXMLCharState.iequals(localname) == 0)
return true;
- if (iequals("scxml", localName))
+ if (kXMLCharScxml.iequals(localname) == 0)
return true;
- if (iequals("parallel", localName))
+ if (kXMLCharParallel.iequals(localname) == 0)
return true;
- if (iequals("final", localName))
+ if (kXMLCharFinal.iequals(localname) == 0)
return true;
if (properOnly)
return false;
- if (iequals("history", localName))
+ if (kXMLCharHistory.iequals(localname) == 0)
return true;
- if (iequals("initial", localName))
+ if (kXMLCharInitial.iequals(localname) == 0)
return true;
return false;
diff --git a/test/src/test-lifecycle.cpp b/test/src/test-lifecycle.cpp
index e948e3c..6b30c96 100644
--- a/test/src/test-lifecycle.cpp
+++ b/test/src/test-lifecycle.cpp
@@ -48,67 +48,67 @@ std::list<CallbackType> callBackSeq;
class SequenceCheckingMonitor : public InterpreterMonitor {
- virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event) {
+ virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREPROCESSINGEVENT);
}
- virtual void beforeMicroStep(Interpreter& interpreter) {
+ virtual void beforeMicroStep(const std::string& sessionId) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREMICROSTEP);
}
- virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
+ virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREEXITINGSTATE);
}
- virtual void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
+ virtual void afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
CHECK_CALLBACK_TYPE(USCXML_AFTEREXITINGSTATE);
}
- virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* element) {
+ virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREEXECUTINGCONTENT);
}
- virtual void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* element) {
+ virtual void afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) {
CHECK_CALLBACK_TYPE(USCXML_AFTEREXECUTINGCONTENT);
}
- virtual void beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ virtual void beforeUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREUNINVOKING);
}
- virtual void afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ virtual void afterUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
CHECK_CALLBACK_TYPE(USCXML_AFTERUNINVOKING);
}
- virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
+ virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
CHECK_CALLBACK_TYPE(USCXML_BEFORETAKINGTRANSITION);
}
- virtual void afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
+ virtual void afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
CHECK_CALLBACK_TYPE(USCXML_AFTERTAKINGTRANSITION);
}
- virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
+ virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREENTERINGSTATE);
}
- virtual void afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
+ virtual void afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
CHECK_CALLBACK_TYPE(USCXML_AFTERENTERINGSTATE);
}
- virtual void beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ virtual void beforeInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
CHECK_CALLBACK_TYPE(USCXML_BEFOREINVOKING);
}
- virtual void afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ virtual void afterInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
CHECK_CALLBACK_TYPE(USCXML_AFTERINVOKING);
}
- virtual void afterMicroStep(Interpreter& interpreter) {
+ virtual void afterMicroStep(const std::string& sessionId) {
CHECK_CALLBACK_TYPE(USCXML_AFTERMICROSTEP);
}
- virtual void onStableConfiguration(Interpreter& interpreter) {
+ virtual void onStableConfiguration(const std::string& sessionId) {
CHECK_CALLBACK_TYPE(USCXML_ONSTABLECONFIGURATION);
}
- virtual void beforeCompletion(Interpreter& interpreter) {
+ virtual void beforeCompletion(const std::string& sessionId) {
CHECK_CALLBACK_TYPE(USCXML_BEFORECOMPLETION);
}
- virtual void afterCompletion(Interpreter& interpreter) {
+ virtual void afterCompletion(const std::string& sessionId) {
CHECK_CALLBACK_TYPE(USCXML_AFTERCOMPLETION);
}
diff --git a/test/src/test-serialization.cpp b/test/src/test-serialization.cpp
index 968bae3..da8df89 100644
--- a/test/src/test-serialization.cpp
+++ b/test/src/test-serialization.cpp
@@ -21,7 +21,7 @@ int lastTransitionAt;
//class StatusMonitor : public uscxml::InterpreterMonitor {
class StatusMonitor : public uscxml::StateTransitionMonitor {
- void beforeTakingTransition(uscxml::Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
+ void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
lastTransitionAt = time(NULL);
}
@@ -65,6 +65,7 @@ int main(int argc, char** argv) {
}
DirectoryWatch* watcher = new DirectoryWatch(argv[optind], true);
+ watcher->setLogger(Logger::getDefault());
watcher->updateEntries(true);
std::map<std::string, struct stat> entries = watcher->getAllEntries();
@@ -92,7 +93,7 @@ int main(int argc, char** argv) {
lastTransitionAt = time(NULL);
std::string sourceXML = std::string(argv[optind]) + PATH_SEPERATOR + entryIter->first;
- sourceXML = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test557.scxml";
+// sourceXML = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test557.scxml";
Interpreter interpreter = Interpreter::fromURL(sourceXML);
LOGD(USCXML_INFO) << "Processing " << interpreter.getImpl()->getBaseURL() << std::endl;
diff --git a/test/src/test-stress.cpp b/test/src/test-stress.cpp
index 4d395ab..e034e87 100644
--- a/test/src/test-stress.cpp
+++ b/test/src/test-stress.cpp
@@ -19,7 +19,7 @@ int startedAt;
int lastTransitionAt;
class StatusMonitor : public uscxml::InterpreterMonitor {
- void beforeTakingTransition(uscxml::Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
+ void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
lastTransitionAt = time(NULL);
}
diff --git a/test/src/test-validating.cpp b/test/src/test-validating.cpp
index ae2a2f5..a0fd6dd 100644
--- a/test/src/test-validating.cpp
+++ b/test/src/test-validating.cpp
@@ -35,7 +35,7 @@ public:
IssueMonitor() {
runtimeIssues = 0;
}
- void reportIssue(Interpreter& intrpreter, const InterpreterIssue& issue) {
+ void reportIssue(const std::string& sessionId, const InterpreterIssue& issue) {
runtimeIssues++;
}
};