summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/Interpreter.cpp33
-rw-r--r--src/uscxml/Interpreter.h34
-rw-r--r--src/uscxml/debug/Benchmark.cpp42
-rw-r--r--src/uscxml/debug/Benchmark.h10
-rw-r--r--src/uscxml/debug/DebugSession.cpp8
-rw-r--r--src/uscxml/debug/Debugger.cpp124
-rw-r--r--src/uscxml/debug/Debugger.h72
-rw-r--r--src/uscxml/debug/DebuggerServlet.cpp2
-rw-r--r--src/uscxml/interpreter/BasicContentExecutor.cpp10
-rw-r--r--src/uscxml/interpreter/ContentExecutorImpl.h2
-rw-r--r--src/uscxml/interpreter/FastMicroStep.cpp11
-rw-r--r--src/uscxml/interpreter/FastMicroStep.h13
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.cpp20
-rw-r--r--src/uscxml/interpreter/InterpreterMonitor.h58
-rw-r--r--src/uscxml/interpreter/LargeMicroStep.cpp2285
-rw-r--r--src/uscxml/interpreter/LargeMicroStep.h178
-rw-r--r--src/uscxml/interpreter/MicroStepImpl.h8
-rw-r--r--src/uscxml/plugins/Factory.cpp48
-rw-r--r--src/uscxml/plugins/Factory.h32
-rw-r--r--src/uscxml/transform/ChartToC.cpp22
-rw-r--r--src/uscxml/util/DOM.h4
21 files changed, 1534 insertions, 1482 deletions
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index b20013f..c4025ba 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -82,7 +82,7 @@ Interpreter Interpreter::fromXML(const std::string& xml, const std::string& base
interpreterImpl->_document = parser->adoptDocument();
interpreterImpl->_baseURL = absUrl;
- interpreterImpl->_md5 = md5(xml);
+ interpreterImpl->_md5 = md5(xml);
InterpreterImpl::addInstance(interpreterImpl);
} catch (const XERCESC_NS::SAXParseException& toCatch) {
@@ -151,7 +151,7 @@ Interpreter Interpreter::fromURL(const std::string& url) {
#if 1
// Xercesc is hard to build with SSL on windows, whereas curl uses winssl
- return fromXML(absUrl.getInContent(), absUrl);
+ return fromXML(absUrl.getInContent(), absUrl);
#else
std::shared_ptr<InterpreterImpl> interpreterImpl(new InterpreterImpl());
@@ -191,6 +191,15 @@ Interpreter Interpreter::fromURL(const std::string& url) {
}
+Interpreter Interpreter::fromSessionId(const std::string& sessionId) {
+ std::lock_guard<std::recursive_mutex> lock(InterpreterImpl::_instanceMutex);
+ std::map<std::string, std::weak_ptr<InterpreterImpl> > instances = InterpreterImpl::getInstances();
+ if (instances.find(sessionId) != instances.end()) {
+ return Interpreter(instances[sessionId].lock());
+ }
+ return Interpreter();
+}
+
void Interpreter::reset() {
return _impl->reset();
}
@@ -274,19 +283,20 @@ static void printNodeSet(Logger& logger, const std::list<XERCESC_NS::DOMElement*
std::recursive_mutex StateTransitionMonitor::_mutex;
-void StateTransitionMonitor::beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
+void StateTransitionMonitor::beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
LOG(_logger, USCXML_VERBATIM) << "Transition: " << uscxml::DOMUtils::xPathForNode(transition) << std::endl;
}
-void StateTransitionMonitor::onStableConfiguration(Interpreter& interpreter) {
+void StateTransitionMonitor::onStableConfiguration(const std::string& sessionId) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
+ Interpreter interpreter = Interpreter::fromSessionId(sessionId);
LOG(_logger, USCXML_VERBATIM) << "Stable Config: { ";
printNodeSet(_logger, interpreter.getConfiguration());
LOG(_logger, USCXML_VERBATIM) << " }" << std::endl;
}
-void StateTransitionMonitor::beforeProcessingEvent(Interpreter& interpreter, const uscxml::Event& event) {
+void StateTransitionMonitor::beforeProcessingEvent(const std::string& sessionId, const uscxml::Event& event) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
switch (event.eventType) {
case uscxml::Event::INTERNAL:
@@ -301,24 +311,29 @@ void StateTransitionMonitor::beforeProcessingEvent(Interpreter& interpreter, con
}
}
-void StateTransitionMonitor::beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* element) {
+void StateTransitionMonitor::beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
LOG(_logger, USCXML_VERBATIM) << "Executable Content: " << DOMUtils::xPathForNode(element) << std::endl;
}
-void StateTransitionMonitor::beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
+void StateTransitionMonitor::beforeExitingState(const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
LOG(_logger, USCXML_VERBATIM) << "Exiting: " << (HAS_ATTR(state, kXMLCharId) ? ATTR(state, kXMLCharId) : DOMUtils::xPathForNode(state)) << std::endl;
}
-void StateTransitionMonitor::beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
+void StateTransitionMonitor::beforeEnteringState(const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
LOG(_logger, USCXML_VERBATIM) << "Entering: " << (HAS_ATTR(state, kXMLCharId) ? ATTR(state, kXMLCharId) : DOMUtils::xPathForNode(state)) << std::endl;
}
-void StateTransitionMonitor::beforeMicroStep(Interpreter& interpreter) {
+void StateTransitionMonitor::beforeMicroStep(const std::string& sessionId) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
+ Interpreter interpreter = Interpreter::fromSessionId(sessionId);
LOG(_logger, USCXML_VERBATIM) << "Microstep in config: {";
printNodeSet(_logger, interpreter.getConfiguration());
LOG(_logger, USCXML_VERBATIM) << "}" << std::endl;
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 6075dbc..3c44400 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -122,6 +122,12 @@ public:
static Interpreter fromClone(const Interpreter& other);
/**
+ * Get the instance of an interpreter with a given sessionId.
+ * @param other The session ID.
+ */
+ static Interpreter fromSessionId(const std::string& sessionId);
+
+ /**
* See PIMPL_OPERATORS macro in Common.h
*/
PIMPL_OPERATORS(Interpreter);
@@ -229,15 +235,27 @@ public:
return _impl;
}
#if 0
- // "Ambiguous user-defined-conversion" with operator bool() on MSVC from Visual Studio 12
- explicit operator MicroStepCallbacks*() { return (MicroStepCallbacks*)(_impl.get()); }
- explicit operator DataModelCallbacks*() { return (DataModelCallbacks*)(_impl.get()); }
- explicit operator IOProcessorCallbacks*() { return (IOProcessorCallbacks*)(_impl.get()); }
- explicit operator ContentExecutorCallbacks*() { return (ContentExecutorCallbacks*)(_impl.get()); }
- explicit operator DelayedEventQueueCallbacks*() { return (DelayedEventQueueCallbacks*)(_impl.get()); }
- explicit operator InvokerCallbacks*() { return (InvokerCallbacks*)(_impl.get()); }
+ // "Ambiguous user-defined-conversion" with operator bool() on MSVC from Visual Studio 12
+ explicit operator MicroStepCallbacks*() {
+ return (MicroStepCallbacks*)(_impl.get());
+ }
+ explicit operator DataModelCallbacks*() {
+ return (DataModelCallbacks*)(_impl.get());
+ }
+ explicit operator IOProcessorCallbacks*() {
+ return (IOProcessorCallbacks*)(_impl.get());
+ }
+ explicit operator ContentExecutorCallbacks*() {
+ return (ContentExecutorCallbacks*)(_impl.get());
+ }
+ explicit operator DelayedEventQueueCallbacks*() {
+ return (DelayedEventQueueCallbacks*)(_impl.get());
+ }
+ explicit operator InvokerCallbacks*() {
+ return (InvokerCallbacks*)(_impl.get());
+ }
#endif
-
+
protected:
std::shared_ptr<InterpreterImpl> _impl;
diff --git a/src/uscxml/debug/Benchmark.cpp b/src/uscxml/debug/Benchmark.cpp
index 0d2d789..b529bb4 100644
--- a/src/uscxml/debug/Benchmark.cpp
+++ b/src/uscxml/debug/Benchmark.cpp
@@ -23,33 +23,33 @@ namespace uscxml {
std::mutex Benchmark::benchMutex;
std::map<std::string, size_t> Benchmark::benchmarks;
-
+
Benchmark::Benchmark(const std::string& domain) : domain(domain), started(std::chrono::system_clock::now()) {
}
Benchmark::~Benchmark() {
- std::lock_guard<std::mutex> lock(benchMutex);
- benchmarks[domain] += std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - started).count();
+ std::lock_guard<std::mutex> lock(benchMutex);
+ benchmarks[domain] += std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - started).count();
}
-
+
std::ostream& Benchmark::report(std::ostream& stream) {
- std::lock_guard<std::mutex> lock(benchMutex);
-
- size_t longestDomain = 0;
- for (auto benchmark : benchmarks) {
- longestDomain = (benchmark.first.size() > longestDomain ? benchmark.first.size() : longestDomain);
- }
- longestDomain += 8;
-
- for (auto benchmark : benchmarks) {
- std::string padding;
- for (int i = benchmark.first.size(); i < (longestDomain - log10(benchmark.second)); i++) {
- padding += " ";
- }
-
- stream << benchmark.first << ":" << padding << (double)benchmark.second / 1000.0 << "ms" << std::endl;
- }
- return stream;
+ std::lock_guard<std::mutex> lock(benchMutex);
+
+ size_t longestDomain = 0;
+ for (auto benchmark : benchmarks) {
+ longestDomain = (benchmark.first.size() > longestDomain ? benchmark.first.size() : longestDomain);
+ }
+ longestDomain += 8;
+
+ for (auto benchmark : benchmarks) {
+ std::string padding;
+ for (int i = benchmark.first.size(); i < (longestDomain - log10(benchmark.second)); i++) {
+ padding += " ";
+ }
+
+ stream << benchmark.first << ":" << padding << (double)benchmark.second / 1000.0 << "ms" << std::endl;
+ }
+ return stream;
}
}
diff --git a/src/uscxml/debug/Benchmark.h b/src/uscxml/debug/Benchmark.h
index 82ef583..6548ff8 100644
--- a/src/uscxml/debug/Benchmark.h
+++ b/src/uscxml/debug/Benchmark.h
@@ -34,12 +34,12 @@ class USCXML_API Benchmark {
public:
Benchmark(const std::string& domain);
~Benchmark();
-
- static std::ostream& report(std::ostream& stream);
+
+ static std::ostream& report(std::ostream& stream);
protected:
- std::string domain;
- std::chrono::time_point<std::chrono::system_clock> started;
-
+ std::string domain;
+ std::chrono::time_point<std::chrono::system_clock> started;
+
static std::map<std::string, size_t> benchmarks;
static std::mutex benchMutex;
};
diff --git a/src/uscxml/debug/DebugSession.cpp b/src/uscxml/debug/DebugSession.cpp
index 802b355..42973fc 100644
--- a/src/uscxml/debug/DebugSession.cpp
+++ b/src/uscxml/debug/DebugSession.cpp
@@ -119,7 +119,7 @@ Data DebugSession::debugPrepare(const Data& data) {
if (_interpreter) {
// register ourself as a monitor
_interpreter.addMonitor(_debugger);
- _debugger->attachSession(_interpreter.getImpl().get(), shared_from_this());
+ _debugger->attachSession(_interpreter.getImpl()->getSessionId(), shared_from_this());
replyData.compound["status"] = Data("success", Data::VERBATIM);
} else {
@@ -149,7 +149,7 @@ Data DebugSession::debugAttach(const Data& data) {
std::shared_ptr<InterpreterImpl> instance = weakInstance.second.lock();
if (instance && instance->getSessionId() == interpreterId) {
_interpreter = instance;
- _debugger->attachSession(_interpreter.getImpl().get(), shared_from_this());
+ _debugger->attachSession(_interpreter.getImpl()->getSessionId(), shared_from_this());
interpreterFound = true;
break;
}
@@ -170,7 +170,7 @@ Data DebugSession::debugDetach(const Data& data) {
Data replyData;
_isAttached = false;
- _debugger->detachSession(_interpreter.getImpl().get());
+ _debugger->detachSession(_interpreter.getImpl()->getSessionId());
replyData.compound["status"] = Data("success", Data::VERBATIM);
return replyData;
}
@@ -223,7 +223,7 @@ Data DebugSession::debugStop(const Data& data) {
if (_interpreter) {
// detach from old intepreter
- _debugger->detachSession(_interpreter.getImpl().get());
+ _debugger->detachSession(_interpreter.getImpl()->getSessionId());
}
if (_isRunning && _interpreterThread != NULL) {
diff --git a/src/uscxml/debug/Debugger.cpp b/src/uscxml/debug/Debugger.cpp
index e1ff74b..cd7f0fe 100644
--- a/src/uscxml/debug/Debugger.cpp
+++ b/src/uscxml/debug/Debugger.cpp
@@ -24,9 +24,8 @@
namespace uscxml {
-void Debugger::afterCompletion(Interpreter& interpreter) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::afterCompletion(const std::string& sessionId) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
@@ -35,9 +34,9 @@ void Debugger::afterCompletion(Interpreter& interpreter) {
pushData(session, msg);
}
-void Debugger::beforeCompletion(Interpreter& interpreter) {}
+void Debugger::beforeCompletion(const std::string& sessionId) {}
-std::list<Breakpoint> Debugger::getQualifiedStateBreakpoints(InterpreterImpl* impl, const XERCESC_NS::DOMElement* state, Breakpoint breakpointTemplate) {
+std::list<Breakpoint> Debugger::getQualifiedStateBreakpoints(const std::string& sessionId, const XERCESC_NS::DOMElement* state, Breakpoint breakpointTemplate) {
std::list<Breakpoint> breakpoints;
Breakpoint bp = breakpointTemplate; // copy base as template
@@ -49,7 +48,7 @@ std::list<Breakpoint> Debugger::getQualifiedStateBreakpoints(InterpreterImpl* im
return breakpoints;
}
-std::list<Breakpoint> Debugger::getQualifiedInvokeBreakpoints(InterpreterImpl* impl, const XERCESC_NS::DOMElement* invokeElem, const std::string invokeId, Breakpoint breakpointTemplate) {
+std::list<Breakpoint> Debugger::getQualifiedInvokeBreakpoints(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string invokeId, Breakpoint breakpointTemplate) {
std::list<Breakpoint> breakpoints;
Breakpoint bp = breakpointTemplate; // copy base as template
@@ -60,7 +59,8 @@ std::list<Breakpoint> Debugger::getQualifiedInvokeBreakpoints(InterpreterImpl* i
if (HAS_ATTR(invokeElem, kXMLCharType)) {
bp.invokeType = ATTR(invokeElem, kXMLCharType);
} else if (HAS_ATTR(invokeElem, kXMLCharTypeExpr)) {
- bp.invokeType = impl->evalAsData(ATTR(invokeElem, kXMLCharTypeExpr)).atom;
+ Interpreter intptr = Interpreter::fromSessionId(sessionId);
+ bp.invokeType = intptr.getImpl()->evalAsData(ATTR(invokeElem, kXMLCharTypeExpr)).atom;
}
breakpoints.push_back(bp);
@@ -68,11 +68,13 @@ std::list<Breakpoint> Debugger::getQualifiedInvokeBreakpoints(InterpreterImpl* i
return breakpoints;
}
-std::list<Breakpoint> Debugger::getQualifiedTransBreakpoints(InterpreterImpl* impl, const XERCESC_NS::DOMElement* transition, Breakpoint breakpointTemplate) {
+std::list<Breakpoint> Debugger::getQualifiedTransBreakpoints(const std::string& sessionId, const XERCESC_NS::DOMElement* transition, Breakpoint breakpointTemplate) {
std::list<Breakpoint> breakpoints;
XERCESC_NS::DOMElement* source = getSourceState(transition);
- std::list<XERCESC_NS::DOMElement*> targets = getTargetStates(transition, impl->_scxml);
+ Interpreter intptr = Interpreter::fromSessionId(sessionId);
+
+ std::list<XERCESC_NS::DOMElement*> targets = getTargetStates(transition, intptr.getImpl()->_scxml);
for (auto target : targets) {
@@ -88,59 +90,59 @@ std::list<Breakpoint> Debugger::getQualifiedTransBreakpoints(InterpreterImpl* im
return breakpoints;
}
-void Debugger::beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
- handleTransition(interpreter, transition, Breakpoint::BEFORE);
+void Debugger::beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
+ handleTransition(sessionId, transition, Breakpoint::BEFORE);
}
-void Debugger::afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {
- handleTransition(interpreter, transition, Breakpoint::AFTER);
+void Debugger::afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
+ handleTransition(sessionId, transition, Breakpoint::AFTER);
}
-void Debugger::beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent) {
- handleExecutable(interpreter, execContent, Breakpoint::BEFORE);
+void Debugger::beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent) {
+ handleExecutable(sessionId, execContent, Breakpoint::BEFORE);
}
-void Debugger::afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent) {
- handleExecutable(interpreter, execContent, Breakpoint::AFTER);
+void Debugger::afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent) {
+ handleExecutable(sessionId, execContent, Breakpoint::AFTER);
}
-void Debugger::beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
- handleState(interpreter, state, Breakpoint::BEFORE, Breakpoint::EXIT);
+void Debugger::beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
+ handleState(sessionId, state, Breakpoint::BEFORE, Breakpoint::EXIT);
}
-void Debugger::afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
- handleState(interpreter, state, Breakpoint::AFTER, Breakpoint::EXIT);
+void Debugger::afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
+ handleState(sessionId, state, Breakpoint::AFTER, Breakpoint::EXIT);
}
-void Debugger::beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
- handleState(interpreter, state, Breakpoint::BEFORE, Breakpoint::ENTER);
+void Debugger::beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
+ handleState(sessionId, state, Breakpoint::BEFORE, Breakpoint::ENTER);
}
-void Debugger::afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {
- handleState(interpreter, state, Breakpoint::AFTER, Breakpoint::ENTER);
+void Debugger::afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
+ handleState(sessionId, state, Breakpoint::AFTER, Breakpoint::ENTER);
}
-void Debugger::beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
- handleInvoke(interpreter, invokeElem, invokeid, Breakpoint::BEFORE, Breakpoint::UNINVOKE);
+void Debugger::beforeUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ handleInvoke(sessionId, invokeElem, invokeid, Breakpoint::BEFORE, Breakpoint::UNINVOKE);
}
-void Debugger::afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
- handleInvoke(interpreter, invokeElem, invokeid, Breakpoint::AFTER, Breakpoint::UNINVOKE);
+void Debugger::afterUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ handleInvoke(sessionId, invokeElem, invokeid, Breakpoint::AFTER, Breakpoint::UNINVOKE);
}
-void Debugger::beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
- handleInvoke(interpreter, invokeElem, invokeid, Breakpoint::BEFORE, Breakpoint::INVOKE);
+void Debugger::beforeInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ handleInvoke(sessionId, invokeElem, invokeid, Breakpoint::BEFORE, Breakpoint::INVOKE);
}
-void Debugger::afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
- handleInvoke(interpreter, invokeElem, invokeid, Breakpoint::AFTER, Breakpoint::INVOKE);
+void Debugger::afterInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
+ handleInvoke(sessionId, invokeElem, invokeid, Breakpoint::AFTER, Breakpoint::INVOKE);
}
-void Debugger::onStableConfiguration(Interpreter& interpreter) {
- handleStable(interpreter, Breakpoint::ON);
+void Debugger::onStableConfiguration(const std::string& sessionId) {
+ handleStable(sessionId, Breakpoint::ON);
}
-void Debugger::beforeMicroStep(Interpreter& interpreter) {
- handleMicrostep(interpreter, Breakpoint::BEFORE);
+void Debugger::beforeMicroStep(const std::string& sessionId) {
+ handleMicrostep(sessionId, Breakpoint::BEFORE);
}
-void Debugger::afterMicroStep(Interpreter& interpreter) {
- handleMicrostep(interpreter, Breakpoint::AFTER);
+void Debugger::afterMicroStep(const std::string& sessionId) {
+ handleMicrostep(sessionId, Breakpoint::AFTER);
}
-void Debugger::beforeProcessingEvent(Interpreter& interpreter, const Event& event) {
- handleEvent(interpreter, event, Breakpoint::BEFORE);
+void Debugger::beforeProcessingEvent(const std::string& sessionId, const Event& event) {
+ handleEvent(sessionId, event, Breakpoint::BEFORE);
}
-void Debugger::handleExecutable(Interpreter& interpreter,
+void Debugger::handleExecutable(const std::string& sessionId,
const XERCESC_NS::DOMElement* execContentElem,
Breakpoint::When when) {
- std::shared_ptr<DebugSession> session = getSession(interpreter.getImpl().get());
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -159,9 +161,8 @@ void Debugger::handleExecutable(Interpreter& interpreter,
}
-void Debugger::handleEvent(Interpreter& interpreter, const Event& event, Breakpoint::When when) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::handleEvent(const std::string& sessionId, const Event& event, Breakpoint::When when) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -179,9 +180,8 @@ void Debugger::handleEvent(Interpreter& interpreter, const Event& event, Breakpo
}
-void Debugger::handleStable(Interpreter& interpreter, Breakpoint::When when) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::handleStable(const std::string& sessionId, Breakpoint::When when) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -197,9 +197,8 @@ void Debugger::handleStable(Interpreter& interpreter, Breakpoint::When when) {
session->checkBreakpoints(breakpoints);
}
-void Debugger::handleMicrostep(Interpreter& interpreter, Breakpoint::When when) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::handleMicrostep(const std::string& sessionId, Breakpoint::When when) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -215,9 +214,8 @@ void Debugger::handleMicrostep(Interpreter& interpreter, Breakpoint::When when)
session->checkBreakpoints(breakpoints);
}
-void Debugger::handleTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition, Breakpoint::When when) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::handleTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition, Breakpoint::When when) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -225,13 +223,12 @@ void Debugger::handleTransition(Interpreter& interpreter, const XERCESC_NS::DOME
Breakpoint breakpointTemplate;
breakpointTemplate.when = when;
- std::list<Breakpoint> qualifiedBreakpoints = getQualifiedTransBreakpoints(impl, transition, breakpointTemplate);
+ std::list<Breakpoint> qualifiedBreakpoints = getQualifiedTransBreakpoints(sessionId, transition, breakpointTemplate);
session->checkBreakpoints(qualifiedBreakpoints);
}
-void Debugger::handleState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state, Breakpoint::When when, Breakpoint::Action action) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::handleState(const std::string& sessionId, const XERCESC_NS::DOMElement* state, Breakpoint::When when, Breakpoint::Action action) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -240,14 +237,13 @@ void Debugger::handleState(Interpreter& interpreter, const XERCESC_NS::DOMElemen
Breakpoint breakpointTemplate;
breakpointTemplate.when = when;
breakpointTemplate.action = action;
- std::list<Breakpoint> qualifiedBreakpoints = getQualifiedStateBreakpoints(impl, state, breakpointTemplate);
+ std::list<Breakpoint> qualifiedBreakpoints = getQualifiedStateBreakpoints(sessionId, state, breakpointTemplate);
session->checkBreakpoints(qualifiedBreakpoints);
}
-void Debugger::handleInvoke(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeId, Breakpoint::When when, Breakpoint::Action action) {
- InterpreterImpl* impl = interpreter.getImpl().get();
- std::shared_ptr<DebugSession> session = getSession(impl);
+void Debugger::handleInvoke(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeId, Breakpoint::When when, Breakpoint::Action action) {
+ std::shared_ptr<DebugSession> session = getSession(sessionId);
if (!session)
return;
if (!session->_isRunning)
@@ -256,7 +252,7 @@ void Debugger::handleInvoke(Interpreter& interpreter, const XERCESC_NS::DOMEleme
Breakpoint breakpointTemplate;
breakpointTemplate.when = when;
breakpointTemplate.action = action;
- std::list<Breakpoint> qualifiedBreakpoints = getQualifiedInvokeBreakpoints(impl, invokeElem, invokeId, breakpointTemplate);
+ std::list<Breakpoint> qualifiedBreakpoints = getQualifiedInvokeBreakpoints(sessionId, invokeElem, invokeId, breakpointTemplate);
session->checkBreakpoints(qualifiedBreakpoints);
}
diff --git a/src/uscxml/debug/Debugger.h b/src/uscxml/debug/Debugger.h
index d69e6f6..ec00a95 100644
--- a/src/uscxml/debug/Debugger.h
+++ b/src/uscxml/debug/Debugger.h
@@ -35,80 +35,80 @@ public:
}
virtual ~Debugger() {}
- virtual void attachSession(InterpreterImpl* impl, std::shared_ptr<DebugSession> session) {
+ virtual void attachSession(const std::string& sessionId, std::shared_ptr<DebugSession> session) {
std::lock_guard<std::recursive_mutex> lock(_sessionMutex);
- _sessionForInterpreter[impl] = session;
+ _sessionForInterpreter[sessionId] = session;
}
- virtual void detachSession(InterpreterImpl* impl) {
+ virtual void detachSession(const std::string& sessionId) {
std::lock_guard<std::recursive_mutex> lock(_sessionMutex);
- _sessionForInterpreter.erase(impl);
+ _sessionForInterpreter.erase(sessionId);
}
- virtual std::shared_ptr<DebugSession> getSession(InterpreterImpl* impl) {
+ virtual std::shared_ptr<DebugSession> getSession(const std::string& sessionId) {
std::lock_guard<std::recursive_mutex> lock(_sessionMutex);
- if (_sessionForInterpreter.find(impl) != _sessionForInterpreter.end())
- return _sessionForInterpreter[impl];
+ if (_sessionForInterpreter.find(sessionId) != _sessionForInterpreter.end())
+ return _sessionForInterpreter[sessionId];
return std::shared_ptr<DebugSession>();
}
virtual void pushData(std::shared_ptr<DebugSession> session, Data pushData) = 0;
// InterpreterMonitor
- virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event);
- virtual void beforeMicroStep(Interpreter& interpreter);
- virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state);
- virtual void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state);
- virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent);
- virtual void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent);
- virtual void beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid);
- virtual void afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid);
- virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition);
- virtual void afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition);
- virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state);
- virtual void afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state);
- virtual void beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid);
- virtual void afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid);
- virtual void afterMicroStep(Interpreter& interpreter);
- virtual void onStableConfiguration(Interpreter& interpreter);
- virtual void beforeCompletion(Interpreter& interpreter);
- virtual void afterCompletion(Interpreter& interpreter);
+ virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event);
+ virtual void beforeMicroStep(const std::string& sessionId);
+ virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state);
+ virtual void afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state);
+ virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent);
+ virtual void afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent);
+ virtual void beforeUninvoking(const std::string& sessionId, 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);
+ virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition);
+ virtual void afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition);
+ virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state);
+ virtual void afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state);
+ virtual void beforeInvoking(const std::string& sessionId, 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);
+ virtual void afterMicroStep(const std::string& sessionId);
+ virtual void onStableConfiguration(const std::string& sessionId);
+ virtual void beforeCompletion(const std::string& sessionId);
+ virtual void afterCompletion(const std::string& sessionId);
protected:
- void handleTransition(Interpreter& interpreter,
+ void handleTransition(const std::string& sessionId,
const XERCESC_NS::DOMElement* transition,
Breakpoint::When when);
- void handleState(Interpreter& interpreter,
+ void handleState(const std::string& sessionId,
const XERCESC_NS::DOMElement* state,
Breakpoint::When when,
Breakpoint::Action action);
- void handleInvoke(Interpreter& interpreter,
+ void handleInvoke(const std::string& sessionId,
const XERCESC_NS::DOMElement* invokeElem,
const std::string& invokeId,
Breakpoint::When when,
Breakpoint::Action action);
- void handleExecutable(Interpreter& interpreter,
+ void handleExecutable(const std::string& sessionId,
const XERCESC_NS::DOMElement* execContentElem,
Breakpoint::When when);
- void handleStable(Interpreter& interpreter, Breakpoint::When when);
- void handleMicrostep(Interpreter& interpreter, Breakpoint::When when);
- void handleEvent(Interpreter& interpreter, const Event& event, Breakpoint::When when);
+ void handleStable(const std::string& sessionId, Breakpoint::When when);
+ void handleMicrostep(const std::string& sessionId, Breakpoint::When when);
+ void handleEvent(const std::string& sessionId, const Event& event, Breakpoint::When when);
- std::list<Breakpoint> getQualifiedTransBreakpoints(InterpreterImpl* impl,
+ std::list<Breakpoint> getQualifiedTransBreakpoints(const std::string& sessionId,
const XERCESC_NS::DOMElement* transition,
Breakpoint breakpointTemplate);
- std::list<Breakpoint> getQualifiedStateBreakpoints(InterpreterImpl* impl,
+ std::list<Breakpoint> getQualifiedStateBreakpoints(const std::string& sessionId,
const XERCESC_NS::DOMElement* state,
Breakpoint breakpointTemplate);
- std::list<Breakpoint> getQualifiedInvokeBreakpoints(InterpreterImpl* impl,
+ std::list<Breakpoint> getQualifiedInvokeBreakpoints(const std::string& sessionId,
const XERCESC_NS::DOMElement* invokeElem,
const std::string invokeId,
Breakpoint breakpointTemplate);
std::recursive_mutex _sessionMutex;
/// @todo: We ought to change form InterpreterImpl to Interpreter everywhere
- std::map<InterpreterImpl*, std::shared_ptr<DebugSession> > _sessionForInterpreter;
+ std::map<std::string, std::shared_ptr<DebugSession> > _sessionForInterpreter;
};
}
diff --git a/src/uscxml/debug/DebuggerServlet.cpp b/src/uscxml/debug/DebuggerServlet.cpp
index 1d2df6e..74853f4 100644
--- a/src/uscxml/debug/DebuggerServlet.cpp
+++ b/src/uscxml/debug/DebuggerServlet.cpp
@@ -210,7 +210,7 @@ void DebuggerServlet::processDisconnect(const HTTPServer::Request& request) {
replyData.compound["reason"] = Data("No such session", Data::VERBATIM);
} else {
replyData.compound["status"] = Data("success", Data::VERBATIM);
- detachSession(_sessionForId[sessionId]->getInterpreter().getImpl().get());
+ detachSession(sessionId);
_sessionForId[sessionId]->debugStop(request.data["content"]);
_clientConns.erase(_sessionForId[sessionId]);
_sendQueues.erase(_sessionForId[sessionId]);
diff --git a/src/uscxml/interpreter/BasicContentExecutor.cpp b/src/uscxml/interpreter/BasicContentExecutor.cpp
index 6572d39..5344957 100644
--- a/src/uscxml/interpreter/BasicContentExecutor.cpp
+++ b/src/uscxml/interpreter/BasicContentExecutor.cpp
@@ -729,11 +729,11 @@ Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element, bool a
return Data(contentSS.str(), Data::INTERPRETED);
// test153, we need to throw for test150 in promela, but we need to space normalize for test558
- try {
- Data d = _callbacks->getAsData(contentSS.str());
- if (!d.empty())
- return d;
- } catch ( ... ) {}
+ try {
+ Data d = _callbacks->getAsData(contentSS.str());
+ if (!d.empty())
+ return d;
+ } catch ( ... ) {}
// test558
return Data(spaceNormalize(contentSS.str()), Data::VERBATIM);
diff --git a/src/uscxml/interpreter/ContentExecutorImpl.h b/src/uscxml/interpreter/ContentExecutorImpl.h
index d837273..c85d9a0 100644
--- a/src/uscxml/interpreter/ContentExecutorImpl.h
+++ b/src/uscxml/interpreter/ContentExecutorImpl.h
@@ -76,7 +76,7 @@ public:
/** Monitoring */
virtual std::set<InterpreterMonitor*> getMonitors() = 0;
- virtual Interpreter getInterpreter() = 0;
+ virtual const std::string& getSessionId() = 0;
virtual Logger getLogger() = 0;
virtual ExecutableContent createExecutableContent(const std::string& localName, const std::string& nameSpace) = 0;
diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp
index 8b91191..d6ad298 100644
--- a/src/uscxml/interpreter/FastMicroStep.cpp
+++ b/src/uscxml/interpreter/FastMicroStep.cpp
@@ -269,6 +269,9 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
_states[i] = new State();
_states[i]->documentOrder = i;
_states[i]->element = tmp.front();
+ if (HAS_ATTR(_states[i]->element, kXMLCharId)) {
+ _states[i]->name = ATTR(_states[i]->element, kXMLCharId);
+ }
_states[i]->element->setUserData(X("uscxmlState"), _states[i], NULL);
_states[i]->completion.resize(_states.size());
_states[i]->ancestors.resize(_states.size());
@@ -995,7 +998,7 @@ ESTABLISH_ENTRYSET:
while(i-- > 0) {
if (BIT_HAS(i, _exitSet) && BIT_HAS(i, _configuration)) {
- USCXML_MONITOR_CALLBACK1(monitors, beforeExitingState, USCXML_GET_STATE(i).element);
+ USCXML_MONITOR_CALLBACK2(monitors, beforeExitingState, USCXML_GET_STATE(i).name, USCXML_GET_STATE(i).element);
/* call all on exit handlers */
for (auto exitIter = USCXML_GET_STATE(i).onExit.begin(); exitIter != USCXML_GET_STATE(i).onExit.end(); exitIter++) {
@@ -1007,7 +1010,7 @@ ESTABLISH_ENTRYSET:
}
BIT_CLEAR(i, _configuration);
- USCXML_MONITOR_CALLBACK1(monitors, afterExitingState, USCXML_GET_STATE(i).element);
+ USCXML_MONITOR_CALLBACK2(monitors, afterExitingState, USCXML_GET_STATE(i).name, USCXML_GET_STATE(i).element);
}
}
@@ -1058,7 +1061,7 @@ ESTABLISH_ENTRYSET:
continue;
}
- USCXML_MONITOR_CALLBACK1(monitors, beforeEnteringState, USCXML_GET_STATE(i).element);
+ USCXML_MONITOR_CALLBACK2(monitors, beforeEnteringState, USCXML_GET_STATE(i).name, USCXML_GET_STATE(i).element);
BIT_SET_AT(i, _configuration);
@@ -1079,7 +1082,7 @@ ESTABLISH_ENTRYSET:
}
}
- USCXML_MONITOR_CALLBACK1(monitors, afterEnteringState, USCXML_GET_STATE(i).element);
+ USCXML_MONITOR_CALLBACK2(monitors, afterEnteringState, USCXML_GET_STATE(i).name, USCXML_GET_STATE(i).element);
/* take history and initial transitions */
j = _transSet.find_first();
diff --git a/src/uscxml/interpreter/FastMicroStep.h b/src/uscxml/interpreter/FastMicroStep.h
index 1b743ef..5ff1117 100644
--- a/src/uscxml/interpreter/FastMicroStep.h
+++ b/src/uscxml/interpreter/FastMicroStep.h
@@ -54,8 +54,10 @@ public:
virtual ~FastMicroStep();
virtual std::shared_ptr<MicroStepImpl> create(MicroStepCallbacks* callbacks);
- std::string getName() { return "fast"; }
-
+ std::string getName() {
+ return "fast";
+ }
+
virtual InterpreterState step(size_t blockMs);
virtual void reset();
virtual bool isInState(const std::string& stateId);
@@ -66,8 +68,8 @@ public:
virtual Data serialize();
protected:
- FastMicroStep() {}; // only for factory
-
+ FastMicroStep() {}; // only for factory
+
class Transition {
public:
Transition() : element(NULL), source(0), onTrans(NULL), type(0) {}
@@ -104,6 +106,7 @@ protected:
std::list<XERCESC_NS::DOMElement*> onEntry;
std::list<XERCESC_NS::DOMElement*> onExit;
XERCESC_NS::DOMElement* doneData;
+ std::string name;
unsigned char type;
};
@@ -166,7 +169,7 @@ private:
void printStateNames(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset);
#endif
- friend class Factory;
+ friend class Factory;
};
}
diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp
index 00fbf41..9e59cea 100644
--- a/src/uscxml/interpreter/InterpreterImpl.cpp
+++ b/src/uscxml/interpreter/InterpreterImpl.cpp
@@ -338,15 +338,15 @@ void InterpreterImpl::init() {
// try to open chached data from resource directory
std::string sharedTemp = URL::getTempDir(true);
std::ifstream dataFS(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache");
- try {
- if (dataFS.is_open()) {
- std::string cacheStr((std::istreambuf_iterator<char>(dataFS)),
- std::istreambuf_iterator<char>());
- _cache = Data::fromJSON(cacheStr);
- }
- } catch (...) {
- remove(std::string(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache").c_str());
- }
+ try {
+ if (dataFS.is_open()) {
+ std::string cacheStr((std::istreambuf_iterator<char>(dataFS)),
+ std::istreambuf_iterator<char>());
+ _cache = Data::fromJSON(cacheStr);
+ }
+ } catch (...) {
+ remove(std::string(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache").c_str());
+ }
// get md5 of current document
std::stringstream ss;
@@ -390,7 +390,7 @@ void InterpreterImpl::init() {
}
if (!_microStepper) {
- _microStepper = MicroStep(std::shared_ptr<MicroStepImpl>(new LargeMicroStep(this)));
+ _microStepper = MicroStep(std::shared_ptr<MicroStepImpl>(new FastMicroStep(this)));
}
_microStepper.init(_scxml);
diff --git a/src/uscxml/interpreter/InterpreterMonitor.h b/src/uscxml/interpreter/InterpreterMonitor.h
index 70cac0c..43b7f53 100644
--- a/src/uscxml/interpreter/InterpreterMonitor.h
+++ b/src/uscxml/interpreter/InterpreterMonitor.h
@@ -35,17 +35,17 @@ if (_state == USCXML_DESTROYED) { throw std::bad_weak_ptr(); }
#define USCXML_MONITOR_CALLBACK(callbacks, function) { \
if (callbacks.size() > 0) {\
-Interpreter inptr = _callbacks->getInterpreter(); \
+const std::string& inptr = _callbacks->getSessionId(); \
for (auto callback : callbacks) { callback->function(inptr); } } }
#define USCXML_MONITOR_CALLBACK1(callbacks, function, arg1) { \
if (callbacks.size() > 0) {\
-Interpreter inptr = _callbacks->getInterpreter(); \
+const std::string& inptr = _callbacks->getSessionId(); \
for (auto callback : callbacks) { callback->function(inptr, arg1); } } }
#define USCXML_MONITOR_CALLBACK2(callbacks, function, arg1, arg2) { \
if (callbacks.size() > 0) {\
-Interpreter inptr = _callbacks->getInterpreter(); \
+const std::string& inptr = _callbacks->getSessionId(); \
for (auto callback : callbacks) { callback->function(inptr, arg1, arg2); } } }
// forward declare
@@ -65,34 +65,34 @@ public:
InterpreterMonitor(Logger logger) : _copyToInvokers(false), _logger(logger) {}
virtual ~InterpreterMonitor() {}
- virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event) {}
- virtual void beforeMicroStep(Interpreter& interpreter) {}
+ virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event) {}
+ virtual void beforeMicroStep(const std::string& sessionId) {}
- virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {}
- virtual void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {}
+ virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {}
+ virtual void afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {}
- virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent) {}
- virtual void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* execContent) {}
+ virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent) {}
+ virtual void afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* execContent) {}
- virtual void beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {}
- virtual void afterUninvoking(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) {}
+ virtual void afterUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {}
- virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {}
- virtual void afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) {}
+ virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {}
+ virtual void afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {}
- virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {}
- virtual void afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) {}
+ virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {}
+ virtual void afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {}
- virtual void beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {}
- virtual void afterInvoking(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) {}
+ virtual void afterInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {}
- virtual void afterMicroStep(Interpreter& interpreter) {}
- virtual void onStableConfiguration(Interpreter& interpreter) {}
+ virtual void afterMicroStep(const std::string& sessionId) {}
+ virtual void onStableConfiguration(const std::string& sessionId) {}
- virtual void beforeCompletion(Interpreter& interpreter) {}
- virtual void afterCompletion(Interpreter& interpreter) {}
+ virtual void beforeCompletion(const std::string& sessionId) {}
+ virtual void afterCompletion(const std::string& sessionId) {}
- virtual void reportIssue(Interpreter& interpreter, const InterpreterIssue& issue) {}
+ virtual void reportIssue(const std::string& sessionId, const InterpreterIssue& issue) {}
void copyToInvokers(bool copy) {
_copyToInvokers = copy;
@@ -112,13 +112,13 @@ public:
StateTransitionMonitor(std::string prefix = "") : _logPrefix(prefix) {}
virtual ~StateTransitionMonitor() {}
- virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition);
- virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* element);
- virtual void onStableConfiguration(Interpreter& interpreter);
- virtual void beforeProcessingEvent(Interpreter& interpreter, const uscxml::Event& event);
- virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state);
- virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state);
- virtual void beforeMicroStep(Interpreter& interpreter);
+ virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition);
+ virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element);
+ virtual void onStableConfiguration(const std::string& sessionId);
+ virtual void beforeProcessingEvent(const std::string& sessionId, const uscxml::Event& event);
+ virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state);
+ virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state);
+ virtual void beforeMicroStep(const std::string& sessionId);
protected:
static std::recursive_mutex _mutex;
diff --git a/src/uscxml/interpreter/LargeMicroStep.cpp b/src/uscxml/interpreter/LargeMicroStep.cpp
index 83900c8..eab303c 100644
--- a/src/uscxml/interpreter/LargeMicroStep.cpp
+++ b/src/uscxml/interpreter/LargeMicroStep.cpp
@@ -74,12 +74,12 @@ using namespace XERCESC_NS;
* Print name of states contained in a (debugging).
*/
void LargeMicroStep::printStateNames(const boost::container::flat_set<LargeMicroStep::State*, LargeMicroStep::StateOrder>& a) {
- const char* seperator = "";
- for (auto state : a) {
- std::cerr << seperator << (HAS_ATTR(state->element, X("id")) ? ATTR(state->element, X("id")) : "UNK");
- seperator = ", ";
- }
- std::cerr << std::endl;
+ const char* seperator = "";
+ for (auto state : a) {
+ std::cerr << seperator << (HAS_ATTR(state->element, X("id")) ? ATTR(state->element, X("id")) : "UNK");
+ seperator = ", ";
+ }
+ std::cerr << std::endl;
}
#endif
@@ -87,1220 +87,1225 @@ LargeMicroStep::LargeMicroStep(MicroStepCallbacks* callbacks) : MicroStepImpl(ca
}
std::shared_ptr<MicroStepImpl> LargeMicroStep::create(MicroStepCallbacks* callbacks) {
- return std::shared_ptr<MicroStepImpl>(new LargeMicroStep(callbacks));
+ return std::shared_ptr<MicroStepImpl>(new LargeMicroStep(callbacks));
}
LargeMicroStep::~LargeMicroStep() {
- for (size_t i = 0; i < _states.size(); i++) {
- delete(_states[i]);
- }
- for (size_t i = 0; i < _transitions.size(); i++) {
- delete(_transitions[i]);
- }
+ for (size_t i = 0; i < _states.size(); i++) {
+ delete(_states[i]);
+ }
+ for (size_t i = 0; i < _transitions.size(); i++) {
+ delete(_transitions[i]);
+ }
}
std::list<XERCESC_NS::DOMElement*> LargeMicroStep::getConfiguration() {
- std::list<XERCESC_NS::DOMElement*> config;
- for (auto state : _configuration) {
- config.push_back(state->element);
- }
- return config;
+ std::list<XERCESC_NS::DOMElement*> config;
+ for (auto state : _configuration) {
+ config.push_back(state->element);
+ }
+ return config;
}
void LargeMicroStep::markAsCancelled() {
- _isCancelled = true;
+ _isCancelled = true;
}
void LargeMicroStep::reset() {
- _isCancelled = false;
- _flags = USCXML_CTX_PRISTINE;
- _configuration.clear();
- _configurationPostFix.clear();
- _history.clear();
- _initializedData.clear();
- _invocations.clear();
-
+ _isCancelled = false;
+ _flags = USCXML_CTX_PRISTINE;
+ _configuration.clear();
+ _configurationPostFix.clear();
+ _history.clear();
+ _initializedData.clear();
+ _invocations.clear();
+
}
bool LargeMicroStep::isInState(const std::string& stateId) {
#ifdef USCXML_VERBOSE
- printStateNames(_configuration);
+ printStateNames(_configuration);
#endif
- for (auto state : _configuration) {
- if (HAS_ATTR(state->element, kXMLCharId) && ATTR(state->element, kXMLCharId) == stateId)
- return true;
- }
- return false;
+ for (auto state : _configuration) {
+ if (HAS_ATTR(state->element, kXMLCharId) && ATTR(state->element, kXMLCharId) == stateId)
+ return true;
+ }
+ return false;
}
std::list<DOMElement*> LargeMicroStep::getHistoryCompletion(const DOMElement* history) {
- std::set<std::string> elements;
- elements.insert(_xmlPrefix.str() + "history");
- std::list<DOMElement*> histories = DOMUtils::inPostFixOrder(elements, _scxml);
-
- std::list<DOMElement*> covered;
- std::list<DOMElement*> perParentcovered;
- const DOMNode* parent = NULL;
-
- std::list<DOMElement*> completion;
-
- if (parent != history->getParentNode()) {
- covered.insert(covered.end(), perParentcovered.begin(), perParentcovered.end());
- perParentcovered.clear();
- parent = history->getParentNode();
- }
-
- bool deep = (HAS_ATTR(history, kXMLCharType) && iequals(ATTR(history, kXMLCharType), "deep"));
-
- for (size_t j = 0; j < _states.size(); j++) {
- if (_states[j]->element == history)
- continue;
-
- if (DOMUtils::isDescendant((DOMNode*)_states[j]->element, history->getParentNode()) && isHistory(_states[j]->element)) {
- ((DOMElement*)history)->setUserData(X("hasHistoryChild"), _states[j], NULL);
- }
-
- if (DOMUtils::isMember(_states[j]->element, covered))
- continue;
-
- if (deep) {
- if (DOMUtils::isDescendant(_states[j]->element, history->getParentNode()) && !isHistory(_states[j]->element)) {
- completion.push_back(_states[j]->element);
- }
- } else {
- if (_states[j]->element->getParentNode() == history->getParentNode() && !isHistory(_states[j]->element)) {
- completion.push_back(_states[j]->element);
- }
- }
- }
-
- return completion;
+ std::set<std::string> elements;
+ elements.insert(_xmlPrefix.str() + "history");
+ std::list<DOMElement*> histories = DOMUtils::inPostFixOrder(elements, _scxml);
+
+ std::list<DOMElement*> covered;
+ std::list<DOMElement*> perParentcovered;
+ const DOMNode* parent = NULL;
+
+ std::list<DOMElement*> completion;
+
+ if (parent != history->getParentNode()) {
+ covered.insert(covered.end(), perParentcovered.begin(), perParentcovered.end());
+ perParentcovered.clear();
+ parent = history->getParentNode();
+ }
+
+ bool deep = (HAS_ATTR(history, kXMLCharType) && iequals(ATTR(history, kXMLCharType), "deep"));
+
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (_states[j]->element == history)
+ continue;
+
+ if (DOMUtils::isDescendant((DOMNode*)_states[j]->element, history->getParentNode()) && isHistory(_states[j]->element)) {
+ ((DOMElement*)history)->setUserData(X("hasHistoryChild"), _states[j], NULL);
+ }
+
+ if (DOMUtils::isMember(_states[j]->element, covered))
+ continue;
+
+ if (deep) {
+ if (DOMUtils::isDescendant(_states[j]->element, history->getParentNode()) && !isHistory(_states[j]->element)) {
+ completion.push_back(_states[j]->element);
+ }
+ } else {
+ if (_states[j]->element->getParentNode() == history->getParentNode() && !isHistory(_states[j]->element)) {
+ completion.push_back(_states[j]->element);
+ }
+ }
+ }
+
+ return completion;
}
std::list<DOMElement*> LargeMicroStep::getCompletion(const DOMElement* state) {
- if (isHistory(state)) {
- // we already did in setHistoryCompletion
- return getHistoryCompletion(state);
-
- } else if (isParallel(state)) {
- return getChildStates(state);
-
- } else if (HAS_ATTR(state, kXMLCharInitial)) {
- return getStates(tokenize(ATTR(state, kXMLCharInitial)), _scxml);
-
- } else {
- std::list<DOMElement*> completion;
-
- std::list<DOMElement*> initElems = DOMUtils::filterChildElements(_xmlPrefix.str() + "initial", state);
- if(initElems.size() > 0) {
- // initial element is first child
- completion.push_back(initElems.front());
- } else {
- // first child state
- for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) {
- if (isState(childElem)) {
- completion.push_back(childElem);
- break;
- }
- }
- }
- return completion;
- }
+ if (isHistory(state)) {
+ // we already did in setHistoryCompletion
+ return getHistoryCompletion(state);
+
+ } else if (isParallel(state)) {
+ return getChildStates(state);
+
+ } else if (HAS_ATTR(state, kXMLCharInitial)) {
+ return getStates(tokenize(ATTR(state, kXMLCharInitial)), _scxml);
+
+ } else {
+ std::list<DOMElement*> completion;
+
+ std::list<DOMElement*> initElems = DOMUtils::filterChildElements(_xmlPrefix.str() + "initial", state);
+ if(initElems.size() > 0) {
+ // initial element is first child
+ completion.push_back(initElems.front());
+ } else {
+ // first child state
+ for (auto childElem = state->getFirstElementChild(); childElem; childElem = childElem->getNextElementSibling()) {
+ if (isState(childElem)) {
+ completion.push_back(childElem);
+ break;
+ }
+ }
+ }
+ return completion;
+ }
}
void LargeMicroStep::init(XERCESC_NS::DOMElement* scxml) {
- _scxml = scxml;
- _binding = (HAS_ATTR(_scxml, kXMLCharBinding) && iequals(ATTR(_scxml, kXMLCharBinding), "late") ? LATE : EARLY);
- _xmlPrefix = _scxml->getPrefix();
- _xmlNS = _scxml->getNamespaceURI();
- if (_xmlPrefix) {
- _xmlPrefix = std::string(_xmlPrefix) + ":";
- }
-
- {
- BENCHMARK("init resort states")
- resortStates(_scxml, _xmlPrefix);
- }
-
- std::set<std::string> stateIds;
-
- /** -- All things states -- */
-
- std::list<XERCESC_NS::DOMElement*> tmp;
- size_t i, j;
-
- tmp = DOMUtils::inDocumentOrder({
- _xmlPrefix.str() + "state",
- _xmlPrefix.str() + "parallel",
- _xmlPrefix.str() + "scxml",
- _xmlPrefix.str() + "initial",
- _xmlPrefix.str() + "final",
- _xmlPrefix.str() + "history"
- }, _scxml);
-
- _states.resize(tmp.size());
-
- for (i = 0; i < _states.size(); i++) {
- _states[i] = new State(i);
- _states[i]->element = tmp.front();
- _states[i]->element->setUserData(X("uscxmlState"), _states[i], NULL);
- tmp.pop_front();
- }
- assert(tmp.size() == 0);
-
- if (_binding == Binding::EARLY && _states.size() > 0) {
- // add all data elements to the first state
- std::list<DOMElement*> dataModels = DOMUtils::filterChildElements(_xmlPrefix.str() + "datamodel", _states[0]->element, true);
- dataModels.erase(std::remove_if(dataModels.begin(),
- dataModels.end(),
- [this](DOMElement* elem) {
- return !areFromSameMachine(elem, _scxml);
- }),
- dataModels.end());
-
- std::list<XERCESC_NS::DOMElement*> dataList = DOMUtils::filterChildElements(_xmlPrefix.str() + "data", dataModels, false);
- _states[0]->data = { std::make_move_iterator(std::begin(dataList)), std::make_move_iterator(std::end(dataList))};
- }
-
- for (i = 0; i < _states.size(); i++) {
- // collect states with an id attribute
- if (HAS_ATTR(_states[i]->element, kXMLCharId)) {
- stateIds.insert(ATTR(_states[i]->element, kXMLCharId));
- }
-
- // TODO: Reserve space for ancestors? => Measure performance!
-
- // check for executable content and datamodels
- if (_states[i]->element->getChildElementCount() > 0) {
- // not every child element will be a child state, but we can shrink later
- _states[i]->children.reserve(_states[i]->element->getChildElementCount());
-
- std::list<XERCESC_NS::DOMElement*> entryList = DOMUtils::filterChildElements(_xmlPrefix.str() + "onentry", _states[i]->element);
- std::list<XERCESC_NS::DOMElement*> exitList = DOMUtils::filterChildElements(_xmlPrefix.str() + "onexit", _states[i]->element);
- std::list<XERCESC_NS::DOMElement*> invokeList = DOMUtils::filterChildElements(_xmlPrefix.str() + "invoke", _states[i]->element);
- _states[i]->onEntry = { std::make_move_iterator(std::begin(entryList)), std::make_move_iterator(std::end(entryList))};
- _states[i]->onExit = { std::make_move_iterator(std::begin(exitList)), std::make_move_iterator(std::end(exitList))};
- _states[i]->invoke = { std::make_move_iterator(std::begin(invokeList)), std::make_move_iterator(std::end(invokeList))};
-
- if (i == 0) {
- // have global scripts as onentry of <scxml>
- std::list<XERCESC_NS::DOMElement*> scriptList = DOMUtils::filterChildElements(_xmlPrefix.str() + "script", _states[i]->element, false);
- _states[i]->onEntry = { std::make_move_iterator(std::begin(scriptList)), std::make_move_iterator(std::end(scriptList))};
- }
-
- std::list<DOMElement*> doneDatas = DOMUtils::filterChildElements(_xmlPrefix.str() + "donedata", _states[i]->element);
- if (doneDatas.size() > 0) {
- _states[i]->doneData = doneDatas.front();
- }
-
- if (_binding == Binding::LATE) {
- std::list<DOMElement*> dataModels = DOMUtils::filterChildElements(_xmlPrefix.str() + "datamodel", _states[i]->element);
- if (dataModels.size() > 0) {
- std::list<XERCESC_NS::DOMElement*> dataList = DOMUtils::filterChildElements(_xmlPrefix.str() + "data", dataModels, false);
- _states[i]->data = { std::make_move_iterator(std::begin(dataList)), std::make_move_iterator(std::end(dataList))};
- }
- }
-
- }
-
- // set the states type
- if (false) {
- } else if (iequals(TAGNAME(_states[i]->element), _xmlPrefix.str() + "initial")) {
- _states[i]->type = USCXML_STATE_INITIAL;
- } else if (isFinal(_states[i]->element)) {
- _states[i]->type = USCXML_STATE_FINAL;
- } else if (isHistory(_states[i]->element)) {
- if (HAS_ATTR(_states[i]->element, kXMLCharType) && iequals(ATTR(_states[i]->element, kXMLCharType), "deep")) {
- _states[i]->type = USCXML_STATE_HISTORY_DEEP;
- } else {
- _states[i]->type = USCXML_STATE_HISTORY_SHALLOW;
- }
- } else if (isAtomic(_states[i]->element)) {
- _states[i]->type = USCXML_STATE_ATOMIC;
- } else if (isParallel(_states[i]->element)) {
- _states[i]->type = USCXML_STATE_PARALLEL;
- } else { // <scxml> and any other state
- _states[i]->type = USCXML_STATE_COMPOUND;
- }
-
- // establish the states' completion
- std::list<DOMElement*> completionList = getCompletion(_states[i]->element);
- for (j = 0; completionList.size() > 0; j++) {
- _states[i]->completion.insert((State*)completionList.front()->getUserData(X("uscxmlState")));
- completionList.pop_front();
- }
- assert(completionList.size() == 0);
-
- // this is set when establishing the completion
- if (_states[i]->element->getUserData(X("hasHistoryChild")) == _states[i]) {
- _states[i]->type |= USCXML_STATE_HAS_HISTORY;
- }
-
- // set the states parent and add us as a children
- DOMNode* parent = _states[i]->element->getParentNode();
- if (parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) {
- _states[i]->parent = (State*)parent->getUserData(X("uscxmlState"));
- if (_states[i]->parent != NULL) {
- _states[i]->parent->children.push_back(_states[i]);
- _states[i]->ancestors.insert(_states[i]->parent);
- _states[i]->ancestors.insert(_states[i]->parent->ancestors.begin(), _states[i]->parent->ancestors.end());
- }
- }
- }
-
- /** -- All things transitions -- */
-
- tmp = DOMUtils::inPostFixOrder({
- XML_PREFIX(_scxml).str() + "scxml",
- XML_PREFIX(_scxml).str() + "state",
- XML_PREFIX(_scxml).str() + "final",
- XML_PREFIX(_scxml).str() + "history",
- XML_PREFIX(_scxml).str() + "initial",
- XML_PREFIX(_scxml).str() + "parallel"
- }, _scxml);
- tmp = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "transition", tmp);
-
- _transitions.resize(tmp.size());
- _conflicting.resize(tmp.size());
- _compatible.resize(tmp.size());
-
- for (i = 0; i < _transitions.size(); i++) {
- _transitions[i] = new Transition(i);
- _transitions[i]->element = tmp.front();
- _transitions[i]->element->setUserData(X("uscxmlTrans"), _transitions[i], NULL);
- tmp.pop_front();
- }
- assert(tmp.size() == 0);
-
-
- for (i = 0; i < _transitions.size(); i++) {
- // establish the transitions' target set
- {
- std::list<std::string> targets = tokenize(ATTR(_transitions[i]->element, kXMLCharTarget));
- _transitions[i]->target.reserve(targets.size());
-
- for (auto tIter = targets.begin(); tIter != targets.end(); tIter++) {
- if (stateIds.find(*tIter) != stateIds.end()) {
- _transitions[i]->target.push_back((State*)getState(*tIter, _scxml)->getUserData(X("uscxmlState")));
- }
- }
- }
-
- // the transition's type
- if (!HAS_ATTR(_transitions[i]->element, kXMLCharTarget)) {
- _transitions[i]->type |= USCXML_TRANS_TARGETLESS;
- }
-
- if (HAS_ATTR(_transitions[i]->element, kXMLCharType) && iequals(ATTR(_transitions[i]->element, kXMLCharType), "internal")) {
- _transitions[i]->type |= USCXML_TRANS_INTERNAL;
- }
-
- if (!HAS_ATTR(_transitions[i]->element, kXMLCharEvent)) {
- _transitions[i]->type |= USCXML_TRANS_SPONTANEOUS;
- }
-
- if (iequals(TAGNAME_CAST(_transitions[i]->element->getParentNode()), _xmlPrefix.str() + "history")) {
- _transitions[i]->type |= USCXML_TRANS_HISTORY;
- }
-
- if (iequals(TAGNAME_CAST(_transitions[i]->element->getParentNode()), _xmlPrefix.str() + "initial")) {
- _transitions[i]->type |= USCXML_TRANS_INITIAL;
- }
-
- // the transitions event and condition
- _transitions[i]->event = (HAS_ATTR(_transitions[i]->element, kXMLCharEvent) ?
- ATTR(_transitions[i]->element, kXMLCharEvent) : "");
- _transitions[i]->cond = (HAS_ATTR(_transitions[i]->element, kXMLCharCond) ?
- ATTR(_transitions[i]->element, kXMLCharCond) : "");
-
- // is there executable content?
- if (_transitions[i]->element->getChildElementCount() > 0) {
- _transitions[i]->onTrans = _transitions[i]->element;
- }
-
- }
-
- /* Connect states and transitions */
- for (auto state : _states) {
- std::list<XERCESC_NS::DOMElement*> transList = DOMUtils::filterChildElements(_xmlPrefix.str() + "transition", state->element);
- if (transList.size() > 0) {
- state->transitions.resize(transList.size());
- for (auto i = 0; transList.size() > 0; i++) {
- auto trans = transList.front();
- transList.pop_front();
- Transition* uscxmlTrans = ((Transition*)trans->getUserData(X("uscxmlTrans")));
- uscxmlTrans->source = state;
- // save some memory? => Measure performance!
+ _scxml = scxml;
+ _binding = (HAS_ATTR(_scxml, kXMLCharBinding) && iequals(ATTR(_scxml, kXMLCharBinding), "late") ? LATE : EARLY);
+ _xmlPrefix = _scxml->getPrefix();
+ _xmlNS = _scxml->getNamespaceURI();
+ if (_xmlPrefix) {
+ _xmlPrefix = std::string(_xmlPrefix) + ":";
+ }
+
+ {
+ BENCHMARK("init resort states")
+ resortStates(_scxml, _xmlPrefix);
+ }
+
+ std::set<std::string> stateIds;
+
+ /** -- All things states -- */
+
+ std::list<XERCESC_NS::DOMElement*> tmp;
+ size_t i, j;
+
+ tmp = DOMUtils::inDocumentOrder({
+ _xmlPrefix.str() + "state",
+ _xmlPrefix.str() + "parallel",
+ _xmlPrefix.str() + "scxml",
+ _xmlPrefix.str() + "initial",
+ _xmlPrefix.str() + "final",
+ _xmlPrefix.str() + "history"
+ }, _scxml);
+
+ _states.resize(tmp.size());
+
+ for (i = 0; i < _states.size(); 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);
+ }
+ _states[i]->element->setUserData(X("uscxmlState"), _states[i], NULL);
+ tmp.pop_front();
+ }
+ assert(tmp.size() == 0);
+
+ if (_binding == Binding::EARLY && _states.size() > 0) {
+ // add all data elements to the first state
+ std::list<DOMElement*> dataModels = DOMUtils::filterChildElements(_xmlPrefix.str() + "datamodel", _states[0]->element, true);
+ dataModels.erase(std::remove_if(dataModels.begin(),
+ dataModels.end(),
+ [this](DOMElement* elem) {
+ return !areFromSameMachine(elem, _scxml);
+ }),
+ dataModels.end());
+
+ std::list<XERCESC_NS::DOMElement*> dataList = DOMUtils::filterChildElements(_xmlPrefix.str() + "data", dataModels, false);
+ _states[0]->data = { std::make_move_iterator(std::begin(dataList)), std::make_move_iterator(std::end(dataList))};
+ }
+
+ for (i = 0; i < _states.size(); i++) {
+ // collect states with an id attribute
+ if (HAS_ATTR(_states[i]->element, kXMLCharId)) {
+ stateIds.insert(ATTR(_states[i]->element, kXMLCharId));
+ }
+
+ // TODO: Reserve space for ancestors? => Measure performance!
+
+ // check for executable content and datamodels
+ if (_states[i]->element->getChildElementCount() > 0) {
+ // not every child element will be a child state, but we can shrink later
+ _states[i]->children.reserve(_states[i]->element->getChildElementCount());
+
+ std::list<XERCESC_NS::DOMElement*> entryList = DOMUtils::filterChildElements(_xmlPrefix.str() + "onentry", _states[i]->element);
+ std::list<XERCESC_NS::DOMElement*> exitList = DOMUtils::filterChildElements(_xmlPrefix.str() + "onexit", _states[i]->element);
+ std::list<XERCESC_NS::DOMElement*> invokeList = DOMUtils::filterChildElements(_xmlPrefix.str() + "invoke", _states[i]->element);
+ _states[i]->onEntry = { std::make_move_iterator(std::begin(entryList)), std::make_move_iterator(std::end(entryList))};
+ _states[i]->onExit = { std::make_move_iterator(std::begin(exitList)), std::make_move_iterator(std::end(exitList))};
+ _states[i]->invoke = { std::make_move_iterator(std::begin(invokeList)), std::make_move_iterator(std::end(invokeList))};
+
+ if (i == 0) {
+ // have global scripts as onentry of <scxml>
+ std::list<XERCESC_NS::DOMElement*> scriptList = DOMUtils::filterChildElements(_xmlPrefix.str() + "script", _states[i]->element, false);
+ _states[i]->onEntry = { std::make_move_iterator(std::begin(scriptList)), std::make_move_iterator(std::end(scriptList))};
+ }
+
+ std::list<DOMElement*> doneDatas = DOMUtils::filterChildElements(_xmlPrefix.str() + "donedata", _states[i]->element);
+ if (doneDatas.size() > 0) {
+ _states[i]->doneData = doneDatas.front();
+ }
+
+ if (_binding == Binding::LATE) {
+ std::list<DOMElement*> dataModels = DOMUtils::filterChildElements(_xmlPrefix.str() + "datamodel", _states[i]->element);
+ if (dataModels.size() > 0) {
+ std::list<XERCESC_NS::DOMElement*> dataList = DOMUtils::filterChildElements(_xmlPrefix.str() + "data", dataModels, false);
+ _states[i]->data = { std::make_move_iterator(std::begin(dataList)), std::make_move_iterator(std::end(dataList))};
+ }
+ }
+
+ }
+
+ // set the states type
+ if (false) {
+ } else if (iequals(TAGNAME(_states[i]->element), _xmlPrefix.str() + "initial")) {
+ _states[i]->type = USCXML_STATE_INITIAL;
+ } else if (isFinal(_states[i]->element)) {
+ _states[i]->type = USCXML_STATE_FINAL;
+ } else if (isHistory(_states[i]->element)) {
+ if (HAS_ATTR(_states[i]->element, kXMLCharType) && iequals(ATTR(_states[i]->element, kXMLCharType), "deep")) {
+ _states[i]->type = USCXML_STATE_HISTORY_DEEP;
+ } else {
+ _states[i]->type = USCXML_STATE_HISTORY_SHALLOW;
+ }
+ } else if (isAtomic(_states[i]->element)) {
+ _states[i]->type = USCXML_STATE_ATOMIC;
+ } else if (isParallel(_states[i]->element)) {
+ _states[i]->type = USCXML_STATE_PARALLEL;
+ } else { // <scxml> and any other state
+ _states[i]->type = USCXML_STATE_COMPOUND;
+ }
+
+ // establish the states' completion
+ std::list<DOMElement*> completionList = getCompletion(_states[i]->element);
+ for (j = 0; completionList.size() > 0; j++) {
+ _states[i]->completion.insert((State*)completionList.front()->getUserData(X("uscxmlState")));
+ completionList.pop_front();
+ }
+ assert(completionList.size() == 0);
+
+ // this is set when establishing the completion
+ if (_states[i]->element->getUserData(X("hasHistoryChild")) == _states[i]) {
+ _states[i]->type |= USCXML_STATE_HAS_HISTORY;
+ }
+
+ // set the states parent and add us as a children
+ DOMNode* parent = _states[i]->element->getParentNode();
+ if (parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) {
+ _states[i]->parent = (State*)parent->getUserData(X("uscxmlState"));
+ if (_states[i]->parent != NULL) {
+ _states[i]->parent->children.push_back(_states[i]);
+ _states[i]->ancestors.insert(_states[i]->parent);
+ _states[i]->ancestors.insert(_states[i]->parent->ancestors.begin(), _states[i]->parent->ancestors.end());
+ }
+ }
+ }
+
+ /** -- All things transitions -- */
+
+ tmp = DOMUtils::inPostFixOrder({
+ XML_PREFIX(_scxml).str() + "scxml",
+ XML_PREFIX(_scxml).str() + "state",
+ XML_PREFIX(_scxml).str() + "final",
+ XML_PREFIX(_scxml).str() + "history",
+ XML_PREFIX(_scxml).str() + "initial",
+ XML_PREFIX(_scxml).str() + "parallel"
+ }, _scxml);
+ tmp = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "transition", tmp);
+
+ _transitions.resize(tmp.size());
+ _conflicting.resize(tmp.size());
+ _compatible.resize(tmp.size());
+
+ for (i = 0; i < _transitions.size(); i++) {
+ _transitions[i] = new Transition(i);
+ _transitions[i]->element = tmp.front();
+ _transitions[i]->element->setUserData(X("uscxmlTrans"), _transitions[i], NULL);
+ tmp.pop_front();
+ }
+ assert(tmp.size() == 0);
+
+
+ for (i = 0; i < _transitions.size(); i++) {
+ // establish the transitions' target set
+ {
+ std::list<std::string> targets = tokenize(ATTR(_transitions[i]->element, kXMLCharTarget));
+ _transitions[i]->target.reserve(targets.size());
+
+ for (auto tIter = targets.begin(); tIter != targets.end(); tIter++) {
+ if (stateIds.find(*tIter) != stateIds.end()) {
+ _transitions[i]->target.push_back((State*)getState(*tIter, _scxml)->getUserData(X("uscxmlState")));
+ }
+ }
+ }
+
+ // the transition's type
+ if (!HAS_ATTR(_transitions[i]->element, kXMLCharTarget)) {
+ _transitions[i]->type |= USCXML_TRANS_TARGETLESS;
+ }
+
+ if (HAS_ATTR(_transitions[i]->element, kXMLCharType) && iequals(ATTR(_transitions[i]->element, kXMLCharType), "internal")) {
+ _transitions[i]->type |= USCXML_TRANS_INTERNAL;
+ }
+
+ if (!HAS_ATTR(_transitions[i]->element, kXMLCharEvent)) {
+ _transitions[i]->type |= USCXML_TRANS_SPONTANEOUS;
+ }
+
+ if (iequals(TAGNAME_CAST(_transitions[i]->element->getParentNode()), _xmlPrefix.str() + "history")) {
+ _transitions[i]->type |= USCXML_TRANS_HISTORY;
+ }
+
+ if (iequals(TAGNAME_CAST(_transitions[i]->element->getParentNode()), _xmlPrefix.str() + "initial")) {
+ _transitions[i]->type |= USCXML_TRANS_INITIAL;
+ }
+
+ // the transitions event and condition
+ _transitions[i]->event = (HAS_ATTR(_transitions[i]->element, kXMLCharEvent) ?
+ ATTR(_transitions[i]->element, kXMLCharEvent) : "");
+ _transitions[i]->cond = (HAS_ATTR(_transitions[i]->element, kXMLCharCond) ?
+ ATTR(_transitions[i]->element, kXMLCharCond) : "");
+
+ // is there executable content?
+ if (_transitions[i]->element->getChildElementCount() > 0) {
+ _transitions[i]->onTrans = _transitions[i]->element;
+ }
+
+ }
+
+ /* Connect states and transitions */
+ for (auto state : _states) {
+ std::list<XERCESC_NS::DOMElement*> transList = DOMUtils::filterChildElements(_xmlPrefix.str() + "transition", state->element);
+ if (transList.size() > 0) {
+ state->transitions.resize(transList.size());
+ for (auto i = 0; transList.size() > 0; i++) {
+ auto trans = transList.front();
+ transList.pop_front();
+ Transition* uscxmlTrans = ((Transition*)trans->getUserData(X("uscxmlTrans")));
+ uscxmlTrans->source = state;
+ // save some memory? => Measure performance!
// uscxmlTrans->compatible.shrink_to_fit();
// uscxmlTrans->exitSet.shrink_to_fit();
-
- state->transitions[i] = uscxmlTrans;
- }
- // we need the postfix order for iterating transitions of active states
- state->postFixOrder = (*(state->transitions.begin()))->postFixOrder;
- } else {
- state->postFixOrder = std::numeric_limits<uint32_t>::max();
- }
-
- // save some memory? => Measure performance!
+
+ state->transitions[i] = uscxmlTrans;
+ }
+ // we need the postfix order for iterating transitions of active states
+ state->postFixOrder = (*(state->transitions.begin()))->postFixOrder;
+ } else {
+ state->postFixOrder = std::numeric_limits<uint32_t>::max();
+ }
+
+ // save some memory? => Measure performance!
// state->ancestors.shrink_to_fit();
- state->children.shrink_to_fit();
+ state->children.shrink_to_fit();
// state->completion.shrink_to_fit();
-
- assert(transList.size() == 0);
- }
-
- _isInitialized = true;
+
+ assert(transList.size() == 0);
+ }
+
+ _isInitialized = true;
}
InterpreterState LargeMicroStep::step(size_t blockMs) {
- if (!_isInitialized) {
- init(_scxml);
- return USCXML_INITIALIZED;
- }
-
- std::set<InterpreterMonitor*> monitors = _callbacks->getMonitors();
-
- _exitSet.clear();
- _entrySet.clear();
- _targetSet.clear();
- _tmpStates.clear();
-
- _compatible.clear();
- _conflicting.clear();
- _transSet.clear();
-
- if (_flags & USCXML_CTX_FINISHED)
- return USCXML_FINISHED;
-
- if (_flags & USCXML_CTX_TOP_LEVEL_FINAL) {
- USCXML_MONITOR_CALLBACK(monitors, beforeCompletion);
-
- /* exit all remaining states */
- for (auto stateIter = _configuration.end() ; stateIter != _configuration.begin() ; /* Do nothing */ ) {
- --stateIter;
- /* call all on exit handlers */
- for (auto onExit : (*stateIter)->onExit) {
- try {
- _callbacks->process(onExit);
- } catch (...) {
- // do nothing and continue with next block
- }
- }
- if (_invocations.find(*stateIter) != _invocations.end()) {
- /* cancel all invokers */
- for (auto invoke : (*stateIter)->invoke) {
- _callbacks->uninvoke(invoke);
- }
- _invocations.clear();
- }
- }
-
- _flags |= USCXML_CTX_FINISHED;
-
- USCXML_MONITOR_CALLBACK(monitors, afterCompletion);
-
- return USCXML_FINISHED;
- }
-
-
- if (_flags == USCXML_CTX_PRISTINE) {
- // TODO: Is this working?
- _targetSet = _states.front()->completion;
- _flags |= USCXML_CTX_SPONTANEOUS | USCXML_CTX_INITIALIZED;
- USCXML_MONITOR_CALLBACK(monitors, beforeMicroStep);
-
- goto ESTABLISH_ENTRYSET;
- }
-
- if (_flags & USCXML_CTX_SPONTANEOUS) {
- _event = Event();
- goto SELECT_TRANSITIONS;
- }
-
-
- if ((_event = _callbacks->dequeueInternal())) {
- USCXML_MONITOR_CALLBACK1(monitors, beforeProcessingEvent, _event);
- goto SELECT_TRANSITIONS;
- }
-
- /* manage uninvocations */
- for (auto invokeIter = _invocations.begin(); invokeIter != _invocations.end();) {
- if (_configuration.find(*invokeIter) == _configuration.end()) {
- /* uninvoke */
- for (auto invoke : (*invokeIter)->invoke) {
- _callbacks->uninvoke(invoke);
- }
- invokeIter = _invocations.erase(invokeIter);
- } else {
- invokeIter++;
- }
- }
-
- /* manage invocations */
- for (auto config : _configuration) {
- if (_invocations.find(config) == _invocations.end()) {
- for (auto invoke : config->invoke) {
- try {
- /* invoke */
- _callbacks->invoke(invoke);
- } catch (ErrorEvent e) {
- LOG(_callbacks->getLogger(), USCXML_WARN) << e;
- // TODO: Shall we deliver the event into the interpreter runtime?
- } catch (...) {
- }
- }
- }
- _invocations.insert(config);
- }
-
- // we dequeued all internal events and ought to signal stable configuration
- if (!(_flags & USCXML_CTX_STABLE)) {
- USCXML_MONITOR_CALLBACK(monitors, onStableConfiguration);
- _microstepConfigurations.clear();
- _flags |= USCXML_CTX_STABLE;
- return USCXML_MACROSTEPPED;
- }
-
- if ((_event = _callbacks->dequeueExternal(blockMs))) {
- USCXML_MONITOR_CALLBACK1(monitors, beforeProcessingEvent, _event);
- goto SELECT_TRANSITIONS;
- }
-
- if (_isCancelled) {
- // finalize and exit
- _flags |= USCXML_CTX_TOP_LEVEL_FINAL;
- return USCXML_CANCELLED;
- }
-
- // if (blocking) // we received the empty event to unblock
- // return USCXML_IDLE; // we return IDLE nevertheless
-
- return USCXML_IDLE;
-
+ if (!_isInitialized) {
+ init(_scxml);
+ return USCXML_INITIALIZED;
+ }
+
+ std::set<InterpreterMonitor*> monitors = _callbacks->getMonitors();
+
+ _exitSet.clear();
+ _entrySet.clear();
+ _targetSet.clear();
+ _tmpStates.clear();
+
+ _compatible.clear();
+ _conflicting.clear();
+ _transSet.clear();
+
+ if (_flags & USCXML_CTX_FINISHED)
+ return USCXML_FINISHED;
+
+ if (_flags & USCXML_CTX_TOP_LEVEL_FINAL) {
+ USCXML_MONITOR_CALLBACK(monitors, beforeCompletion);
+
+ /* exit all remaining states */
+ for (auto stateIter = _configuration.end() ; stateIter != _configuration.begin() ; /* Do nothing */ ) {
+ --stateIter;
+ /* call all on exit handlers */
+ for (auto onExit : (*stateIter)->onExit) {
+ try {
+ _callbacks->process(onExit);
+ } catch (...) {
+ // do nothing and continue with next block
+ }
+ }
+ if (_invocations.find(*stateIter) != _invocations.end()) {
+ /* cancel all invokers */
+ for (auto invoke : (*stateIter)->invoke) {
+ _callbacks->uninvoke(invoke);
+ }
+ _invocations.clear();
+ }
+ }
+
+ _flags |= USCXML_CTX_FINISHED;
+
+ USCXML_MONITOR_CALLBACK(monitors, afterCompletion);
+
+ return USCXML_FINISHED;
+ }
+
+
+ if (_flags == USCXML_CTX_PRISTINE) {
+ // TODO: Is this working?
+ _targetSet = _states.front()->completion;
+ _flags |= USCXML_CTX_SPONTANEOUS | USCXML_CTX_INITIALIZED;
+ USCXML_MONITOR_CALLBACK(monitors, beforeMicroStep);
+
+ goto ESTABLISH_ENTRYSET;
+ }
+
+ if (_flags & USCXML_CTX_SPONTANEOUS) {
+ _event = Event();
+ goto SELECT_TRANSITIONS;
+ }
+
+
+ if ((_event = _callbacks->dequeueInternal())) {
+ USCXML_MONITOR_CALLBACK1(monitors, beforeProcessingEvent, _event);
+ goto SELECT_TRANSITIONS;
+ }
+
+ /* manage uninvocations */
+ for (auto invokeIter = _invocations.begin(); invokeIter != _invocations.end();) {
+ if (_configuration.find(*invokeIter) == _configuration.end()) {
+ /* uninvoke */
+ for (auto invoke : (*invokeIter)->invoke) {
+ _callbacks->uninvoke(invoke);
+ }
+ invokeIter = _invocations.erase(invokeIter);
+ } else {
+ invokeIter++;
+ }
+ }
+
+ /* manage invocations */
+ for (auto config : _configuration) {
+ if (_invocations.find(config) == _invocations.end()) {
+ for (auto invoke : config->invoke) {
+ try {
+ /* invoke */
+ _callbacks->invoke(invoke);
+ } catch (ErrorEvent e) {
+ LOG(_callbacks->getLogger(), USCXML_WARN) << e;
+ // TODO: Shall we deliver the event into the interpreter runtime?
+ } catch (...) {
+ }
+ }
+ }
+ _invocations.insert(config);
+ }
+
+ // we dequeued all internal events and ought to signal stable configuration
+ if (!(_flags & USCXML_CTX_STABLE)) {
+ USCXML_MONITOR_CALLBACK(monitors, onStableConfiguration);
+ _microstepConfigurations.clear();
+ _flags |= USCXML_CTX_STABLE;
+ return USCXML_MACROSTEPPED;
+ }
+
+ if ((_event = _callbacks->dequeueExternal(blockMs))) {
+ USCXML_MONITOR_CALLBACK1(monitors, beforeProcessingEvent, _event);
+ goto SELECT_TRANSITIONS;
+ }
+
+ if (_isCancelled) {
+ // finalize and exit
+ _flags |= USCXML_CTX_TOP_LEVEL_FINAL;
+ return USCXML_CANCELLED;
+ }
+
+ // if (blocking) // we received the empty event to unblock
+ // return USCXML_IDLE; // we return IDLE nevertheless
+
+ return USCXML_IDLE;
+
SELECT_TRANSITIONS:
- // we read an event - unset stable to signal onstable again later
- _flags &= ~USCXML_CTX_STABLE;
-
- {
- BENCHMARK("select transitions");
-
- // iterate active states in postfix order and find transitions
- for (auto stateIter = _configurationPostFix.begin(); stateIter != _configurationPostFix.end();) {
- State* state = *stateIter++;
+ // we read an event - unset stable to signal onstable again later
+ _flags &= ~USCXML_CTX_STABLE;
+
+ {
+ BENCHMARK("select transitions");
+
+ // iterate active states in postfix order and find transitions
+ for (auto stateIter = _configurationPostFix.begin(); stateIter != _configurationPostFix.end();) {
+ State* state = *stateIter++;
// std::cout << (HAS_ATTR(state->element, kXMLCharId) ? ATTR(state->element, kXMLCharId) : "?");
// std::cout << ": " << state->documentOrder << " - " << state->postFixOrder << std::endl;
-
- for (auto transIter = state->transitions.begin(); transIter != state->transitions.end();) {
- Transition* transition = *transIter++;
-
- /* never select history or initial transitions automatically */
- if unlikely(transition->type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL))
- continue;
-
- /* is it spontaneous with an event or vice versa? */
- if ((transition->event.size() == 0 && _event) ||
- (transition->event.size() != 0 && !_event))
- continue;
-
- /* check whether it is explicitly conflicting or compatible, calculate if neither */
- if (_flags & USCXML_CTX_TRANSITION_FOUND) {
- BENCHMARK("select transitions conflict & compatible calc");
-
- if (_conflicting[transition->postFixOrder]) {
- // this transition is explicitly conflicting
- continue;
- }
- if (!_compatible[transition->postFixOrder]) {
- // it is not explicitly compatible, we know nothing!
- BENCHMARK("select transitions conflict & compatible calc no entry");
-
- bool conflicts = false;
- for (auto enabledTrans : _transSet) {
- if (enabledTrans->compatible.find(transition->postFixOrder) != enabledTrans->compatible.end() ||
- (enabledTrans->conflicting.find(transition->postFixOrder) != enabledTrans->conflicting.end())) {
- continue;
- }
-
- std::pair<uint32_t, uint32_t> exit1 = getExitSet(transition);
- std::pair<uint32_t, uint32_t> exit2 = getExitSet(enabledTrans);
-
- if (exit1.first != 0 && exit2.first != 0 && // empty domain
- ((exit1.first <= exit2.first && exit1.second >= exit2.first) ||
- (exit2.first <= exit1.first && exit2.second >= exit1.first))) {
- // it is conflicting!
+
+ for (auto transIter = state->transitions.begin(); transIter != state->transitions.end();) {
+ Transition* transition = *transIter++;
+
+ /* never select history or initial transitions automatically */
+ if unlikely(transition->type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL))
+ continue;
+
+ /* is it spontaneous with an event or vice versa? */
+ if ((transition->event.size() == 0 && _event) ||
+ (transition->event.size() != 0 && !_event))
+ continue;
+
+ /* check whether it is explicitly conflicting or compatible, calculate if neither */
+ if (_flags & USCXML_CTX_TRANSITION_FOUND) {
+ BENCHMARK("select transitions conflict & compatible calc");
+
+ if (_conflicting[transition->postFixOrder]) {
+ // this transition is explicitly conflicting
+ continue;
+ }
+ if (!_compatible[transition->postFixOrder]) {
+ // it is not explicitly compatible, we know nothing!
+ BENCHMARK("select transitions conflict & compatible calc no entry");
+
+ bool conflicts = false;
+ for (auto enabledTrans : _transSet) {
+ if (enabledTrans->compatible.find(transition->postFixOrder) != enabledTrans->compatible.end() ||
+ (enabledTrans->conflicting.find(transition->postFixOrder) != enabledTrans->conflicting.end())) {
+ continue;
+ }
+
+ std::pair<uint32_t, uint32_t> exit1 = getExitSet(transition);
+ std::pair<uint32_t, uint32_t> exit2 = getExitSet(enabledTrans);
+
+ if (exit1.first != 0 && exit2.first != 0 && // empty domain
+ ((exit1.first <= exit2.first && exit1.second >= exit2.first) ||
+ (exit2.first <= exit1.first && exit2.second >= exit1.first))) {
+ // it is conflicting!
// assert(uscxml::conflicts(t1, t2, _scxml));
- transition->conflicting.insert(enabledTrans->postFixOrder);
- enabledTrans->conflicting.insert(transition->postFixOrder);
- conflicts = true;
- break;
- } else {
+ transition->conflicting.insert(enabledTrans->postFixOrder);
+ enabledTrans->conflicting.insert(transition->postFixOrder);
+ conflicts = true;
+ break;
+ } else {
// assert(!uscxml::conflicts(t1, t2, _scxml));
- transition->compatible.insert(enabledTrans->postFixOrder);
- enabledTrans->compatible.insert(transition->postFixOrder);
- }
- }
- if (conflicts)
- continue;
- }
- }
-
- /* is it matched? */
- if (_event && !_callbacks->isMatched(_event, transition->event))
- continue;
-
- /* is it enabled? */
- if (transition->cond.size() > 0 && !_callbacks->isTrue(transition->cond))
- continue;
-
- // This transition is fine and ought to be taken!
-
- /* update conflicting and compatible transitions */
- if (_flags & USCXML_CTX_TRANSITION_FOUND) {
- BENCHMARK("select transitions conflict & compatible update");
-
- /* remove all compatible transitions not listed in ours */
- size_t i = _compatible.find_first();
- while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
- if (transition->compatible.find(i) == transition->compatible.end()) {
- _compatible[i] = false;
- }
- i = _compatible.find_next(i);
- }
-
- /* add all conflicting transitions listed in ours */
- for (auto conflict : transition->conflicting) {
- _conflicting[conflict] = true;
- }
-
- } else {
- /* Very first transition added to optimally transition set */
- for (auto compatible : transition->compatible) {
- _compatible[compatible] = true;
- }
- for (auto conflict : transition->conflicting) {
- _conflicting[conflict] = true;
- }
- }
-
- /* remember that we found a transition */
- _flags |= USCXML_CTX_TRANSITION_FOUND;
-
- /* states that are directly targeted (complete as entry-set later) */
- _targetSet.insert(transition->target.begin(), transition->target.end());
-
- /* lazily initialize exit set */
- if (transition->exitSet.first == 0 && transition->exitSet.second == 0) {
+ transition->compatible.insert(enabledTrans->postFixOrder);
+ enabledTrans->compatible.insert(transition->postFixOrder);
+ }
+ }
+ if (conflicts)
+ continue;
+ }
+ }
+
+ /* is it matched? */
+ if (_event && !_callbacks->isMatched(_event, transition->event))
+ continue;
+
+ /* is it enabled? */
+ if (transition->cond.size() > 0 && !_callbacks->isTrue(transition->cond))
+ continue;
+
+ // This transition is fine and ought to be taken!
+
+ /* update conflicting and compatible transitions */
+ if (_flags & USCXML_CTX_TRANSITION_FOUND) {
+ BENCHMARK("select transitions conflict & compatible update");
+
+ /* remove all compatible transitions not listed in ours */
+ size_t i = _compatible.find_first();
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
+ if (transition->compatible.find(i) == transition->compatible.end()) {
+ _compatible[i] = false;
+ }
+ i = _compatible.find_next(i);
+ }
+
+ /* add all conflicting transitions listed in ours */
+ for (auto conflict : transition->conflicting) {
+ _conflicting[conflict] = true;
+ }
+
+ } else {
+ /* Very first transition added to optimally transition set */
+ for (auto compatible : transition->compatible) {
+ _compatible[compatible] = true;
+ }
+ for (auto conflict : transition->conflicting) {
+ _conflicting[conflict] = true;
+ }
+ }
+
+ /* remember that we found a transition */
+ _flags |= USCXML_CTX_TRANSITION_FOUND;
+
+ /* states that are directly targeted (complete as entry-set later) */
+ _targetSet.insert(transition->target.begin(), transition->target.end());
+
+ /* lazily initialize exit set */
+ if (transition->exitSet.first == 0 && transition->exitSet.second == 0) {
// DOMElement* tmp = getTransitionDomain(transition->element, _scxml);
// State* domain1 = tmp == NULL ? NULL : (State*)tmp->getUserData(X("uscxmlState"));
// uint32_t domain2 = getTransitionDomain(transition);
// assert(domain1 == NULL ? domain2 == std::numeric_limits<uint32_t>::max() : domain1->documentOrder == domain2);
-
+
// std::pair<uint32_t, uint32_t> orig = getExitSetCached(transition->element, _scxml);
- transition->exitSet = getExitSet(transition);
+ transition->exitSet = getExitSet(transition);
// assert(transition->exitSet == orig);
- }
-
- /* states that will be left */
- for (auto config : _configuration) {
- if (config->documentOrder >= transition->exitSet.first && config->documentOrder <= transition->exitSet.second) {
- _exitSet.insert(config);
- }
- }
- _transSet.insert(transition);
-
- // break and exit loop if we are at the end
- if (stateIter == _configurationPostFix.end())
- break;
-
- /* move to next possible state that can have optimally enabled transitions */
- auto nextIter = stateIter;
- nextIter++; // advance by one
- while(nextIter != _configurationPostFix.end() && *nextIter == (*stateIter)->parent) {
- // advance until we found a non-ancestor
- nextIter++;
- stateIter++;
- }
-
- break; // next state
- }
- }
+ }
+
+ /* states that will be left */
+ for (auto config : _configuration) {
+ if (config->documentOrder >= transition->exitSet.first && config->documentOrder <= transition->exitSet.second) {
+ _exitSet.insert(config);
+ }
+ }
+ _transSet.insert(transition);
+
+ // break and exit loop if we are at the end
+ if (stateIter == _configurationPostFix.end())
+ break;
+
+ /* move to next possible state that can have optimally enabled transitions */
+ auto nextIter = stateIter;
+ nextIter++; // advance by one
+ while(nextIter != _configurationPostFix.end() && *nextIter == (*stateIter)->parent) {
+ // advance until we found a non-ancestor
+ nextIter++;
+ stateIter++;
+ }
+
+ break; // next state
+ }
+ }
// std::cout << "." << iters << std::flush;
- }
-
- if (_flags & USCXML_CTX_TRANSITION_FOUND) {
- // trigger more sppontaneuous transitions
- _flags |= USCXML_CTX_SPONTANEOUS;
- _flags &= ~USCXML_CTX_TRANSITION_FOUND;
- } else {
- // spontaneuous transitions are exhausted and we will attempt to dequeue an internal event next round
- _flags &= ~USCXML_CTX_SPONTANEOUS;
- return USCXML_MICROSTEPPED;
- }
-
- USCXML_MONITOR_CALLBACK(monitors, beforeMicroStep);
-
+ }
+
+ if (_flags & USCXML_CTX_TRANSITION_FOUND) {
+ // trigger more sppontaneuous transitions
+ _flags |= USCXML_CTX_SPONTANEOUS;
+ _flags &= ~USCXML_CTX_TRANSITION_FOUND;
+ } else {
+ // spontaneuous transitions are exhausted and we will attempt to dequeue an internal event next round
+ _flags &= ~USCXML_CTX_SPONTANEOUS;
+ return USCXML_MICROSTEPPED;
+ }
+
+ USCXML_MONITOR_CALLBACK(monitors, beforeMicroStep);
+
#ifdef USCXML_VERBOSE
- std::cerr << "Targets: ";
- printStateNames(_targetSet);
+ std::cerr << "Targets: ";
+ printStateNames(_targetSet);
#endif
-
+
#ifdef USCXML_VERBOSE
- std::cerr << "ExitSet: ";
- printStateNames(_exitSet);
+ std::cerr << "ExitSet: ";
+ printStateNames(_exitSet);
#endif
-
-
- /* REMEMBER_HISTORY: */
- {
- BENCHMARK("remember history");
-
- for (auto state : _states) {
- if likely(USCXML_STATE_MASK(state->type) != USCXML_STATE_HISTORY_SHALLOW &&
- USCXML_STATE_MASK(state->type) != USCXML_STATE_HISTORY_DEEP)
- continue;
-
- if likely(_exitSet.find(state->parent) == _exitSet.end())
- continue;
-
- /* a history state whose parent is about to be exited */
- for (auto completion : state->completion) {
- if (_configuration.find(completion) != _configuration.end()) {
- _history.insert(completion);
- } else {
- _history.erase(completion);
- }
- }
- }
- }
-
+
+
+ /* REMEMBER_HISTORY: */
+ {
+ BENCHMARK("remember history");
+
+ for (auto state : _states) {
+ if likely(USCXML_STATE_MASK(state->type) != USCXML_STATE_HISTORY_SHALLOW &&
+ USCXML_STATE_MASK(state->type) != USCXML_STATE_HISTORY_DEEP)
+ continue;
+
+ if likely(_exitSet.find(state->parent) == _exitSet.end())
+ continue;
+
+ /* a history state whose parent is about to be exited */
+ for (auto completion : state->completion) {
+ if (_configuration.find(completion) != _configuration.end()) {
+ _history.insert(completion);
+ } else {
+ _history.erase(completion);
+ }
+ }
+ }
+ }
+
#ifdef USCXML_VERBOSE
- std::cerr << "History: ";
- printStateNames(_history);
+ std::cerr << "History: ";
+ printStateNames(_history);
#endif
ESTABLISH_ENTRYSET:
- /* calculate new entry set */
- _entrySet = _targetSet;
-
+ /* calculate new entry set */
+ _entrySet = _targetSet;
+
#ifdef USCXML_VERBOSE
- std::cerr << "Targets: ";
- printStateNames(_targetSet);
+ std::cerr << "Targets: ";
+ printStateNames(_targetSet);
#endif
- /* make sure iterators are not invalidated, TODO: we can know the actual maximum number by syntactic analysis */
- _entrySet.reserve(_states.size());
-
- /* iterate for ancestors */
- {
- BENCHMARK("add ancestors");
- // running from back to front allows us to add parents only due to document order
- for (auto stateIter = _entrySet.end() ; stateIter != _entrySet.begin() ; /* Do nothing */ ) {
- --stateIter;
- if ((*stateIter)->parent) {
- stateIter = ++(_entrySet.insert((*stateIter)->parent).first);
- }
- }
- }
-
- /* iterate for descendants */
- {
- BENCHMARK("add descendants");
- // we cannot use the simplified for loop as inserting will invalidate those iterators
- for (auto stateIter = _entrySet.begin(); stateIter != _entrySet.end(); stateIter++ ) {
- State* state = *stateIter;
-
- switch (USCXML_STATE_MASK(state->type)) {
- case USCXML_STATE_FINAL:
- case USCXML_STATE_ATOMIC:
- break;
-
- case USCXML_STATE_PARALLEL: {
- BENCHMARK("add descendants parallel");
- _entrySet.insert(state->completion.begin(), state->completion.end());
- break;
- }
-
- case USCXML_STATE_HISTORY_SHALLOW:
- case USCXML_STATE_HISTORY_DEEP: {
- BENCHMARK("add descendants history");
- if (_configuration.find(state->parent) == _configuration.end() &&
- !intersects(state->completion.begin(), state->completion.end(), _history.begin(), _history.end())) {
-
- /* nothing set for history, look for a default transition */
- for (auto transition : state->transitions) {
- _entrySet.insert(transition->target.begin(), transition->target.end());
-
- if(USCXML_STATE_MASK(state->type) == USCXML_STATE_HISTORY_DEEP &&
- !intersects(transition->target.begin(), transition->target.end(), state->children.begin(), state->children.end())) {
-
- // add all the target's ancestors
- for (auto target : transition->target) {
+ /* make sure iterators are not invalidated, TODO: we can know the actual maximum number by syntactic analysis */
+ _entrySet.reserve(_states.size());
+
+ /* iterate for ancestors */
+ {
+ BENCHMARK("add ancestors");
+ // running from back to front allows us to add parents only due to document order
+ for (auto stateIter = _entrySet.end() ; stateIter != _entrySet.begin() ; /* Do nothing */ ) {
+ --stateIter;
+ if ((*stateIter)->parent) {
+ stateIter = ++(_entrySet.insert((*stateIter)->parent).first);
+ }
+ }
+ }
+
+ /* iterate for descendants */
+ {
+ BENCHMARK("add descendants");
+ // we cannot use the simplified for loop as inserting will invalidate those iterators
+ for (auto stateIter = _entrySet.begin(); stateIter != _entrySet.end(); stateIter++ ) {
+ State* state = *stateIter;
+
+ switch (USCXML_STATE_MASK(state->type)) {
+ case USCXML_STATE_FINAL:
+ case USCXML_STATE_ATOMIC:
+ break;
+
+ case USCXML_STATE_PARALLEL: {
+ BENCHMARK("add descendants parallel");
+ _entrySet.insert(state->completion.begin(), state->completion.end());
+ break;
+ }
+
+ case USCXML_STATE_HISTORY_SHALLOW:
+ case USCXML_STATE_HISTORY_DEEP: {
+ BENCHMARK("add descendants history");
+ if (_configuration.find(state->parent) == _configuration.end() &&
+ !intersects(state->completion.begin(), state->completion.end(), _history.begin(), _history.end())) {
+
+ /* nothing set for history, look for a default transition */
+ for (auto transition : state->transitions) {
+ _entrySet.insert(transition->target.begin(), transition->target.end());
+
+ if(USCXML_STATE_MASK(state->type) == USCXML_STATE_HISTORY_DEEP &&
+ !intersects(transition->target.begin(), transition->target.end(), state->children.begin(), state->children.end())) {
+
+ // add all the target's ancestors
+ for (auto target : transition->target) {
#if 1
- _entrySet.insert(target->ancestors.begin(), target->ancestors.end());
+ _entrySet.insert(target->ancestors.begin(), target->ancestors.end());
#else
- State* anc = target->parent;
- while(anc != NULL && _entrySet.find(anc) == _entrySet.end()) {
- _entrySet.insert(anc);
- anc = anc->parent;
- }
+ State* anc = target->parent;
+ while(anc != NULL && _entrySet.find(anc) == _entrySet.end()) {
+ _entrySet.insert(anc);
+ anc = anc->parent;
+ }
#endif
- }
- }
- _transSet.insert(transition);
- break;
- }
- } else {
- _tmpStates = state->completion;
- for (auto iter = _tmpStates.begin(); iter != _tmpStates.end();) {
- if (_history.find(*iter) == _history.end()) {
- iter = _tmpStates.erase(iter);
- } else {
- iter++;
- }
- }
- _entrySet.insert(_tmpStates.begin(), _tmpStates.end());
-
- if (state->type == (USCXML_STATE_HAS_HISTORY | USCXML_STATE_HISTORY_DEEP)) {
- /* a deep history state with nested histories -> more completion */
- for (auto histState : state->completion) {
- if (!(histState->type & USCXML_STATE_HAS_HISTORY))
- continue;
-
- if (_entrySet.find(histState) == _entrySet.end())
- continue;
-
- for (auto histChild : histState->children) {
- if ((USCXML_STATE_MASK(histChild->type) == USCXML_STATE_HISTORY_DEEP ||
- USCXML_STATE_MASK(histChild->type) == USCXML_STATE_HISTORY_SHALLOW)) {
- // We can leverage that deep history assignments are already completed and skip a few states in outer loop
- stateIter = _entrySet.insert(histChild).first;
- }
- }
- }
- }
- }
- break;
- }
-
- case USCXML_STATE_INITIAL: {
- BENCHMARK("add descendants initial");
- for (auto transition : state->transitions) {
- _transSet.insert(transition); // remember transition for onentry later
-
- for (auto target : transition->target) {
- _entrySet.insert(target);
- // add all states between target and this state
+ }
+ }
+ _transSet.insert(transition);
+ break;
+ }
+ } else {
+ _tmpStates = state->completion;
+ for (auto iter = _tmpStates.begin(); iter != _tmpStates.end();) {
+ if (_history.find(*iter) == _history.end()) {
+ iter = _tmpStates.erase(iter);
+ } else {
+ iter++;
+ }
+ }
+ _entrySet.insert(_tmpStates.begin(), _tmpStates.end());
+
+ if (state->type == (USCXML_STATE_HAS_HISTORY | USCXML_STATE_HISTORY_DEEP)) {
+ /* a deep history state with nested histories -> more completion */
+ for (auto histState : state->completion) {
+ if (!(histState->type & USCXML_STATE_HAS_HISTORY))
+ continue;
+
+ if (_entrySet.find(histState) == _entrySet.end())
+ continue;
+
+ for (auto histChild : histState->children) {
+ if ((USCXML_STATE_MASK(histChild->type) == USCXML_STATE_HISTORY_DEEP ||
+ USCXML_STATE_MASK(histChild->type) == USCXML_STATE_HISTORY_SHALLOW)) {
+ // We can leverage that deep history assignments are already completed and skip a few states in outer loop
+ stateIter = _entrySet.insert(histChild).first;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case USCXML_STATE_INITIAL: {
+ BENCHMARK("add descendants initial");
+ for (auto transition : state->transitions) {
+ _transSet.insert(transition); // remember transition for onentry later
+
+ for (auto target : transition->target) {
+ _entrySet.insert(target);
+ // add all states between target and this state
#if 1
- _entrySet.insert(target->ancestors.begin(), target->ancestors.end());
+ _entrySet.insert(target->ancestors.begin(), target->ancestors.end());
#else
- State* anc = target->parent;
- while(anc != NULL && anc != state) {
- _entrySet.insert(anc);
- anc = anc->parent;
- }
+ State* anc = target->parent;
+ while(anc != NULL && anc != state) {
+ _entrySet.insert(anc);
+ anc = anc->parent;
+ }
#endif
- }
- }
- break;
- }
-
- case USCXML_STATE_COMPOUND: {
- BENCHMARK("add descendants compound");
-
- /* Compound state may already be complete */
- {
- BENCHMARK("add descendants compound intersect entry/child");
- for (auto child : state->children) {
- /* one child is already in entry_set */
- if (_entrySet.find(child) != _entrySet.end())
- goto NEXT_DESCENDANT;
- /* one child is already active and not left */
- if (_exitSet.find(child) == _exitSet.end() && _configuration.find(child) != _configuration.end())
- goto NEXT_DESCENDANT;
- }
- }
-
- // completion of a compound maybe multiple states via initial attribute
- _entrySet.insert(state->completion.begin(), state->completion.end());
-
- /* deep completion */
- {
- BENCHMARK("add descendants compound deep completion");
- for (auto completion : state->completion) {
-
- if (std::binary_search(state->children.begin(), state->children.end(), completion))
- continue;
-
- // add deep completions ancestors
+ }
+ }
+ break;
+ }
+
+ case USCXML_STATE_COMPOUND: {
+ BENCHMARK("add descendants compound");
+
+ /* Compound state may already be complete */
+ {
+ BENCHMARK("add descendants compound intersect entry/child");
+ for (auto child : state->children) {
+ /* one child is already in entry_set */
+ if (_entrySet.find(child) != _entrySet.end())
+ goto NEXT_DESCENDANT;
+ /* one child is already active and not left */
+ if (_exitSet.find(child) == _exitSet.end() && _configuration.find(child) != _configuration.end())
+ goto NEXT_DESCENDANT;
+ }
+ }
+
+ // completion of a compound maybe multiple states via initial attribute
+ _entrySet.insert(state->completion.begin(), state->completion.end());
+
+ /* deep completion */
+ {
+ BENCHMARK("add descendants compound deep completion");
+ for (auto completion : state->completion) {
+
+ if (std::binary_search(state->children.begin(), state->children.end(), completion))
+ continue;
+
+ // add deep completions ancestors
#if 1
- _entrySet.insert(completion->ancestors.begin(), completion->ancestors.end());
+ _entrySet.insert(completion->ancestors.begin(), completion->ancestors.end());
#else
- State* anc = completion->parent;
- while(anc != NULL && anc != state) {
- _entrySet.insert(anc);
- anc = anc->parent;
- }
+ State* anc = completion->parent;
+ while(anc != NULL && anc != state) {
+ _entrySet.insert(anc);
+ anc = anc->parent;
+ }
#endif
- }
- }
- break;
- }
-
- }
- NEXT_DESCENDANT:;
- }
- }
-
+ }
+ }
+ break;
+ }
+
+ }
+NEXT_DESCENDANT:
+ ;
+ }
+ }
+
#ifdef USCXML_VERBOSE
- std::cerr << "Entering: ";
- printStateNames(_entrySet);
+ std::cerr << "Entering: ";
+ printStateNames(_entrySet);
#endif
- /* EXIT_STATES: */
- {
- BENCHMARK("exit states");
- for (auto stateIter = _exitSet.end() ; stateIter != _exitSet.begin() ; /* Do nothing */ ) {
- State* state = *(--stateIter);
-
- USCXML_MONITOR_CALLBACK1(monitors, beforeExitingState, state->element);
-
- /* call all on exit handlers */
- for (auto exitIter = state->onExit.begin(); exitIter != state->onExit.end(); exitIter++) {
- try {
- _callbacks->process(*exitIter);
- } catch (...) {
- // do nothing and continue with next block
- }
- }
-
- _configuration.erase(state);
- _configurationPostFix.erase(state);
- USCXML_MONITOR_CALLBACK1(monitors, afterExitingState, state->element);
-
- }
- }
-
- /* TAKE_TRANSITIONS: */
- {
- BENCHMARK("take transitions");
- for (auto transition : _transSet) {
- if ((transition->type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) {
- USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, transition->element);
-
- if (transition->onTrans != NULL) {
-
- /* call executable content in non-history, non-initial transition */
- try {
- _callbacks->process(transition->onTrans);
- } catch (...) {
- // do nothing and continue with next block
- }
- }
-
- USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, transition->element);
- }
- }
- }
-
- // remove active state from enter states
- for (auto config : _configuration) {
- if (_entrySet.find(config) != _entrySet.end())
- _entrySet.erase(config);
- }
-
- /* ENTER_STATES: */
- {
- BENCHMARK("enter states");
- for (auto state : _entrySet) {
-
- /* these are no proper states */
- if unlikely(USCXML_STATE_MASK(state->type) == USCXML_STATE_HISTORY_DEEP ||
- USCXML_STATE_MASK(state->type) == USCXML_STATE_HISTORY_SHALLOW ||
- USCXML_STATE_MASK(state->type) == USCXML_STATE_INITIAL) {
- continue;
- }
-
- USCXML_MONITOR_CALLBACK1(monitors, beforeEnteringState, state->element);
-
- _configuration.insert(state);
- _configurationPostFix.insert(state);
-
- /* initialize data */
- if (state->data.size() > 0) {
- if (_initializedData.find(state) == _initializedData.end()) {
- for (auto dataIter = state->data.begin(); dataIter != state->data.end(); dataIter++) {
- _callbacks->initData(*dataIter);
- }
- _initializedData.insert(state);
- }
- }
-
- /* call all on entry handlers */
- for (auto onEntry : state->onEntry) {
- try {
- _callbacks->process(onEntry);
- } catch (...) {
- // do nothing and continue with next block
- }
- }
-
- USCXML_MONITOR_CALLBACK1(monitors, afterEnteringState, state->element);
-
- /* take history and initial transitions */
- for (auto child : state->children) {
- if (child->type != USCXML_STATE_INITIAL &&
- child->type != USCXML_STATE_HISTORY_DEEP &&
- child->type != USCXML_STATE_HISTORY_SHALLOW)
- continue;
-
- for (auto transition : child->transitions) {
- if (!(transition->type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) ||
- _transSet.find(transition) == _transSet.end())
- continue;
-
- USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, transition->element);
-
- /* call executable content in transition */
- if (transition->onTrans != NULL) {
- try {
- _callbacks->process(transition->onTrans);
- } catch (...) {
- // do nothing and continue with next block
- }
- }
-
- USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, transition->element);
- }
-
- }
-
- /* handle final states */
- if unlikely(USCXML_STATE_MASK(state->type) == USCXML_STATE_FINAL) {
- BENCHMARK("enter states final")
- if unlikely(state->parent == _states[0]) {
- // only the topmost scxml is an ancestor
- _flags |= USCXML_CTX_TOP_LEVEL_FINAL;
- } else {
- /* raise done event */
- _callbacks->raiseDoneEvent(state->parent->element, state->doneData);
- }
-
- /**
- * are we the last final state to leave a parallel state?:
- * 1. Gather all parallel states in our ancestor chain
- * 2. Find all states for which these parallels are ancestors
- * 3. Iterate all active final states and remove their ancestors
- * 4. If a state remains, not all children of a parallel are final
- */
- {
- BENCHMARK("enter states final parallel")
-
- State* anc = state->parent;
- while(anc != NULL) {
- if (USCXML_STATE_MASK(anc->type) == USCXML_STATE_PARALLEL) {
- if (isInFinal(anc)) {
- _callbacks->raiseDoneEvent(anc->element, anc->doneData);
- } else {
- break; // ancestors cannot be final either
- }
- }
- anc = anc->parent;
- }
- }
- }
- }
- }
-
- USCXML_MONITOR_CALLBACK(monitors, afterMicroStep);
-
- // are we running in circles?
- if (_microstepConfigurations.find(_configuration) != _microstepConfigurations.end()) {
- InterpreterIssue issue("Reentering same configuration during microstep - possible endless loop",
- NULL,
- InterpreterIssue::USCXML_ISSUE_WARNING);
-
- USCXML_MONITOR_CALLBACK1(monitors,
- reportIssue,
- issue);
- }
- _microstepConfigurations.insert(_configuration);
-
- return USCXML_MICROSTEPPED;
+ /* EXIT_STATES: */
+ {
+ BENCHMARK("exit states");
+ for (auto stateIter = _exitSet.end() ; stateIter != _exitSet.begin() ; /* Do nothing */ ) {
+ State* state = *(--stateIter);
+
+ USCXML_MONITOR_CALLBACK2(monitors, beforeExitingState, state->name, state->element);
+
+ /* call all on exit handlers */
+ for (auto exitIter = state->onExit.begin(); exitIter != state->onExit.end(); exitIter++) {
+ try {
+ _callbacks->process(*exitIter);
+ } catch (...) {
+ // do nothing and continue with next block
+ }
+ }
+
+ _configuration.erase(state);
+ _configurationPostFix.erase(state);
+ USCXML_MONITOR_CALLBACK2(monitors, afterExitingState, state->name, state->element);
+
+ }
+ }
+
+ /* TAKE_TRANSITIONS: */
+ {
+ BENCHMARK("take transitions");
+ for (auto transition : _transSet) {
+ if ((transition->type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) {
+ USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, transition->element);
+
+ if (transition->onTrans != NULL) {
+
+ /* call executable content in non-history, non-initial transition */
+ try {
+ _callbacks->process(transition->onTrans);
+ } catch (...) {
+ // do nothing and continue with next block
+ }
+ }
+
+ USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, transition->element);
+ }
+ }
+ }
+
+ // remove active state from enter states
+ for (auto config : _configuration) {
+ if (_entrySet.find(config) != _entrySet.end())
+ _entrySet.erase(config);
+ }
+
+ /* ENTER_STATES: */
+ {
+ BENCHMARK("enter states");
+ for (auto state : _entrySet) {
+
+ /* these are no proper states */
+ if unlikely(USCXML_STATE_MASK(state->type) == USCXML_STATE_HISTORY_DEEP ||
+ USCXML_STATE_MASK(state->type) == USCXML_STATE_HISTORY_SHALLOW ||
+ USCXML_STATE_MASK(state->type) == USCXML_STATE_INITIAL) {
+ continue;
+ }
+
+ USCXML_MONITOR_CALLBACK2(monitors, beforeEnteringState, state->name, state->element);
+
+ _configuration.insert(state);
+ _configurationPostFix.insert(state);
+
+ /* initialize data */
+ if (state->data.size() > 0) {
+ if (_initializedData.find(state) == _initializedData.end()) {
+ for (auto dataIter = state->data.begin(); dataIter != state->data.end(); dataIter++) {
+ _callbacks->initData(*dataIter);
+ }
+ _initializedData.insert(state);
+ }
+ }
+
+ /* call all on entry handlers */
+ for (auto onEntry : state->onEntry) {
+ try {
+ _callbacks->process(onEntry);
+ } catch (...) {
+ // do nothing and continue with next block
+ }
+ }
+
+ USCXML_MONITOR_CALLBACK2(monitors, afterEnteringState, state->name, state->element);
+
+ /* take history and initial transitions */
+ for (auto child : state->children) {
+ if (child->type != USCXML_STATE_INITIAL &&
+ child->type != USCXML_STATE_HISTORY_DEEP &&
+ child->type != USCXML_STATE_HISTORY_SHALLOW)
+ continue;
+
+ for (auto transition : child->transitions) {
+ if (!(transition->type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) ||
+ _transSet.find(transition) == _transSet.end())
+ continue;
+
+ USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, transition->element);
+
+ /* call executable content in transition */
+ if (transition->onTrans != NULL) {
+ try {
+ _callbacks->process(transition->onTrans);
+ } catch (...) {
+ // do nothing and continue with next block
+ }
+ }
+
+ USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, transition->element);
+ }
+
+ }
+
+ /* handle final states */
+ if unlikely(USCXML_STATE_MASK(state->type) == USCXML_STATE_FINAL) {
+ BENCHMARK("enter states final")
+ if unlikely(state->parent == _states[0]) {
+ // only the topmost scxml is an ancestor
+ _flags |= USCXML_CTX_TOP_LEVEL_FINAL;
+ } else {
+ /* raise done event */
+ _callbacks->raiseDoneEvent(state->parent->element, state->doneData);
+ }
+
+ /**
+ * are we the last final state to leave a parallel state?:
+ * 1. Gather all parallel states in our ancestor chain
+ * 2. Find all states for which these parallels are ancestors
+ * 3. Iterate all active final states and remove their ancestors
+ * 4. If a state remains, not all children of a parallel are final
+ */
+ {
+ BENCHMARK("enter states final parallel")
+
+ State* anc = state->parent;
+ while(anc != NULL) {
+ if (USCXML_STATE_MASK(anc->type) == USCXML_STATE_PARALLEL) {
+ if (isInFinal(anc)) {
+ _callbacks->raiseDoneEvent(anc->element, anc->doneData);
+ } else {
+ break; // ancestors cannot be final either
+ }
+ }
+ anc = anc->parent;
+ }
+ }
+ }
+ }
+ }
+
+ USCXML_MONITOR_CALLBACK(monitors, afterMicroStep);
+
+ // are we running in circles?
+ if (_microstepConfigurations.find(_configuration) != _microstepConfigurations.end()) {
+ InterpreterIssue issue("Reentering same configuration during microstep - possible endless loop",
+ NULL,
+ InterpreterIssue::USCXML_ISSUE_WARNING);
+
+ USCXML_MONITOR_CALLBACK1(monitors,
+ reportIssue,
+ issue);
+ }
+ _microstepConfigurations.insert(_configuration);
+
+ return USCXML_MICROSTEPPED;
}
bool LargeMicroStep::isInFinal(const State* state) {
- switch (USCXML_STATE_MASK(state->type)) {
- case USCXML_STATE_FINAL:
- /* a final state is final */
- return true;
-
- case USCXML_STATE_ATOMIC:
- return false;
-
- case USCXML_STATE_PARALLEL:
- for (auto child : state->children) {
- if (!isInFinal(child))
- return false;
- }
- return true;
-
- case USCXML_STATE_INITIAL:
- return false;
-
- case USCXML_STATE_COMPOUND:
- for (auto child : state->children) {
- if (_configuration.find(child) != _configuration.end()) {
- return isInFinal(child);
- break;
- }
- }
- return true;
-
- default:
- // history
- return true;
- break;
- }
- return false;
+ switch (USCXML_STATE_MASK(state->type)) {
+ case USCXML_STATE_FINAL:
+ /* a final state is final */
+ return true;
+
+ case USCXML_STATE_ATOMIC:
+ return false;
+
+ case USCXML_STATE_PARALLEL:
+ for (auto child : state->children) {
+ if (!isInFinal(child))
+ return false;
+ }
+ return true;
+
+ case USCXML_STATE_INITIAL:
+ return false;
+
+ case USCXML_STATE_COMPOUND:
+ for (auto child : state->children) {
+ if (_configuration.find(child) != _configuration.end()) {
+ return isInFinal(child);
+ break;
+ }
+ }
+ return true;
+
+ default:
+ // history
+ return true;
+ break;
+ }
+ return false;
}
-
+
void LargeMicroStep::resortStates(DOMElement* element, const X& xmlPrefix) {
-
- /**
- initials
- deep histories
- shallow histories
- everything else
- */
-
- // TODO: We can do this in one iteration
-
- DOMElement* child = element->getFirstElementChild();
- while(child) {
- resortStates(child, xmlPrefix);
- child = child->getNextElementSibling();
- }
-
- // shallow history states to top
- child = element->getFirstElementChild();
- while(child) {
- if (TAGNAME_CAST(child) == xmlPrefix.str() + "history" &&
- (!HAS_ATTR(element, kXMLCharType) || iequals(ATTR(element, kXMLCharType), "shallow"))) {
-
- DOMElement* tmp = child->getNextElementSibling();
- if (child != element->getFirstChild()) {
- element->insertBefore(child, element->getFirstChild());
- }
- child = tmp;
- } else {
- child = child->getNextElementSibling();
- }
- }
-
- // deep history states to top
- child = element->getFirstElementChild();
- while(child) {
- if (child->getNodeType() == DOMNode::ELEMENT_NODE &&
- TAGNAME_CAST(child) == xmlPrefix.str() + "history" &&
- HAS_ATTR(element, kXMLCharType) &&
- iequals(ATTR(element, kXMLCharType), "deep")) {
-
- DOMElement* tmp = child->getNextElementSibling();
- if (child != element->getFirstChild()) {
- element->insertBefore(child, element->getFirstChild());
- }
- child = tmp;
- } else {
- child = child->getNextElementSibling();
- }
- }
-
- // initial states on top of histories even
- child = element->getFirstElementChild();
- while(child) {
- if (child->getNodeType() == DOMNode::ELEMENT_NODE && LOCALNAME_CAST(child) == "initial") {
- DOMElement* tmp = child->getNextElementSibling();
- if (child != element->getFirstChild()) {
- element->insertBefore(child, element->getFirstChild());
- }
- child = tmp;
- } else {
- child = child->getNextElementSibling();
- }
- }
+
+ /**
+ initials
+ deep histories
+ shallow histories
+ everything else
+ */
+
+ // TODO: We can do this in one iteration
+
+ DOMElement* child = element->getFirstElementChild();
+ while(child) {
+ resortStates(child, xmlPrefix);
+ child = child->getNextElementSibling();
+ }
+
+ // shallow history states to top
+ child = element->getFirstElementChild();
+ while(child) {
+ if (TAGNAME_CAST(child) == xmlPrefix.str() + "history" &&
+ (!HAS_ATTR(element, kXMLCharType) || iequals(ATTR(element, kXMLCharType), "shallow"))) {
+
+ DOMElement* tmp = child->getNextElementSibling();
+ if (child != element->getFirstChild()) {
+ element->insertBefore(child, element->getFirstChild());
+ }
+ child = tmp;
+ } else {
+ child = child->getNextElementSibling();
+ }
+ }
+
+ // deep history states to top
+ child = element->getFirstElementChild();
+ while(child) {
+ if (child->getNodeType() == DOMNode::ELEMENT_NODE &&
+ TAGNAME_CAST(child) == xmlPrefix.str() + "history" &&
+ HAS_ATTR(element, kXMLCharType) &&
+ iequals(ATTR(element, kXMLCharType), "deep")) {
+
+ DOMElement* tmp = child->getNextElementSibling();
+ if (child != element->getFirstChild()) {
+ element->insertBefore(child, element->getFirstChild());
+ }
+ child = tmp;
+ } else {
+ child = child->getNextElementSibling();
+ }
+ }
+
+ // initial states on top of histories even
+ child = element->getFirstElementChild();
+ while(child) {
+ if (child->getNodeType() == DOMNode::ELEMENT_NODE && LOCALNAME_CAST(child) == "initial") {
+ DOMElement* tmp = child->getNextElementSibling();
+ if (child != element->getFirstChild()) {
+ element->insertBefore(child, element->getFirstChild());
+ }
+ child = tmp;
+ } else {
+ child = child->getNextElementSibling();
+ }
+ }
}
std::pair<uint32_t, uint32_t> LargeMicroStep::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];
+ 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 LargeMicroStep::getTransitionDomain(const Transition* transition) {
- if (transition->target.size() == 0)
- 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(transition->source->type) == USCXML_STATE_COMPOUND) {
- for (auto target : transition->target) {
- if (target->ancestors.find(transition->source) == target->ancestors.end()) {
- goto BREAK_LOOP;
- }
- }
- return transition->source->documentOrder;
- }
+ if (transition->target.size() == 0)
+ 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(transition->source->type) == USCXML_STATE_COMPOUND) {
+ for (auto target : transition->target) {
+ if (target->ancestors.find(transition->source) == target->ancestors.end()) {
+ goto BREAK_LOOP;
+ }
+ }
+ return transition->source->documentOrder;
+ }
BREAK_LOOP:
-
- // find LCCA
- uint32_t ancestor = std::numeric_limits<uint32_t>::max();
-
- // reverse walk up!
- for(auto ancIter = transition->source->ancestors.rbegin(); ancIter != transition->source->ancestors.rend(); ancIter++) {
- State* anc = *ancIter;
-
- // LCCA has to be a compound
- if (!(USCXML_STATE_MASK(anc->type) == USCXML_STATE_COMPOUND))
- continue;
-
- // that contains all states
- for (auto target : transition->target) {
- if (target->ancestors.find(anc) == target->ancestors.end()) {
- goto NEXT_ANCESTOR;
- }
- }
- ancestor = anc->documentOrder;
- break;
- NEXT_ANCESTOR:;
- }
-
- // none found - take uppermost root as ancestor
- if (ancestor == std::numeric_limits<uint32_t>::max())
- return 0;
- return ancestor;
+
+ // find LCCA
+ uint32_t ancestor = std::numeric_limits<uint32_t>::max();
+
+ // reverse walk up!
+ for(auto ancIter = transition->source->ancestors.rbegin(); ancIter != transition->source->ancestors.rend(); ancIter++) {
+ State* anc = *ancIter;
+
+ // LCCA has to be a compound
+ if (!(USCXML_STATE_MASK(anc->type) == USCXML_STATE_COMPOUND))
+ continue;
+
+ // that contains all states
+ for (auto target : transition->target) {
+ if (target->ancestors.find(anc) == target->ancestors.end()) {
+ goto NEXT_ANCESTOR;
+ }
+ }
+ ancestor = anc->documentOrder;
+ break;
+NEXT_ANCESTOR:
+ ;
+ }
+
+ // none found - take uppermost root as ancestor
+ if (ancestor == std::numeric_limits<uint32_t>::max())
+ return 0;
+ return ancestor;
}
-
+
}
diff --git a/src/uscxml/interpreter/LargeMicroStep.h b/src/uscxml/interpreter/LargeMicroStep.h
index 0d7d467..35e21de 100644
--- a/src/uscxml/interpreter/LargeMicroStep.h
+++ b/src/uscxml/interpreter/LargeMicroStep.h
@@ -58,7 +58,9 @@ public:
virtual ~LargeMicroStep();
virtual std::shared_ptr<MicroStepImpl> create(MicroStepCallbacks* callbacks);
- std::string getName() { return "large"; }
+ std::string getName() {
+ return "large";
+ }
virtual InterpreterState step(size_t blockMs);
virtual void reset();
@@ -66,46 +68,51 @@ 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() {
+ return Data();
+ }
protected:
- LargeMicroStep() {} // only for the factory
-
+ 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<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*, StateOrderPostFix> _configurationPostFix;
- boost::container::flat_set<State*, StateOrder> _invocations;
- boost::container::flat_set<State*, StateOrder> _history;
- boost::container::flat_set<State*, StateOrder> _initializedData;
+ 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<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*, StateOrderPostFix> _configurationPostFix;
+ 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
+ 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<uint32_t> compatible;
- boost::container::flat_set<uint32_t> conflicting;
+ boost::container::flat_set<uint32_t> compatible;
+ boost::container::flat_set<uint32_t> conflicting;
std::pair<uint32_t, uint32_t> exitSet;
State* source = NULL;
@@ -122,83 +129,84 @@ protected:
class State {
public:
- State(uint32_t documentOrder) : documentOrder(documentOrder) {}
- const uint32_t documentOrder;
- uint32_t postFixOrder;
+ State(uint32_t documentOrder) : documentOrder(documentOrder) {}
+ const uint32_t documentOrder;
+ uint32_t postFixOrder;
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: leverage!
std::vector<State*> children;
State* parent = NULL;
- std::vector<Transition*> transitions;
+ 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;
+ std::string name;
unsigned char type;
};
- void init(XERCESC_NS::DOMElement* scxml);
+ 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);
- 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;
- 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
- bool _isInitialized = false;
- bool _isCancelled = false;
- Event _event; // we do not care about the event's representation
+ std::list<XERCESC_NS::DOMElement*> _globalScripts;
- std::list<XERCESC_NS::DOMElement*> _globalScripts;
+ Binding _binding;
+ XERCESC_NS::DOMElement* _scxml;
+ X _xmlPrefix;
+ X _xmlNS;
- 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);
+ /// 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::dynamic_bitset<BITSET_BLOCKTYPE> _compatible;
- boost::dynamic_bitset<BITSET_BLOCKTYPE> _conflicting;
-
- 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);
-
- 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;
+ 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::dynamic_bitset<BITSET_BLOCKTYPE> _compatible;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> _conflicting;
+
+ 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);
+
+ 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/MicroStepImpl.h b/src/uscxml/interpreter/MicroStepImpl.h
index 53139bc..df5c07c 100644
--- a/src/uscxml/interpreter/MicroStepImpl.h
+++ b/src/uscxml/interpreter/MicroStepImpl.h
@@ -58,7 +58,7 @@ public:
/** Monitoring */
virtual std::set<InterpreterMonitor*> getMonitors() = 0;
- virtual Interpreter getInterpreter() = 0;
+ virtual const std::string& getSessionId() = 0;
virtual Logger getLogger() = 0;
/** Cache Data */
@@ -91,11 +91,11 @@ public:
virtual void deserialize(const Data& encodedState) = 0;
virtual Data serialize() = 0;
- /// To register at the factory
- virtual std::string getName() = 0;
+ /// To register at the factory
+ virtual std::string getName() = 0;
protected:
- MicroStepImpl() {};
+ MicroStepImpl() {};
MicroStepCallbacks* _callbacks;
};
diff --git a/src/uscxml/plugins/Factory.cpp b/src/uscxml/plugins/Factory.cpp
index 410ac36..9e885e5 100644
--- a/src/uscxml/plugins/Factory.cpp
+++ b/src/uscxml/plugins/Factory.cpp
@@ -133,10 +133,10 @@ Factory::~Factory() {
void Factory::registerPlugins() {
#ifndef FEATS_ON_CMD
- registerMicrostepper(new LargeMicroStep());
- registerMicrostepper(new FastMicroStep());
+ registerMicrostepper(new LargeMicroStep());
+ registerMicrostepper(new FastMicroStep());
#endif
-
+
/*** PLUGINS ***/
#ifdef BUILD_AS_PLUGINS
@@ -507,36 +507,36 @@ std::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const st
#ifndef FEATS_ON_CMD
bool Factory::hasMicroStepper(const std::string& name) {
- if (_microSteppers.find(name) != _microSteppers.end()) {
- return true;
- } else if(_parentFactory) {
- return _parentFactory->hasMicroStepper(name);
- }
- return false;
+ if (_microSteppers.find(name) != _microSteppers.end()) {
+ return true;
+ } else if(_parentFactory) {
+ return _parentFactory->hasMicroStepper(name);
+ }
+ return false;
}
-
+
void Factory::registerMicrostepper(MicroStepImpl* microStepper) {
- _microSteppers[microStepper->getName()] = microStepper;
+ _microSteppers[microStepper->getName()] = microStepper;
}
std::shared_ptr<MicroStepImpl> Factory::createMicroStepper(const std::string& name, MicroStepCallbacks* callbacks) {
- if (_microSteppers.find(name) != _microSteppers.end()) {
- std::shared_ptr<MicroStepImpl> microStepper = _microSteppers[name]->create(callbacks);
- return microStepper;
- }
-
- if (_parentFactory) {
- return _parentFactory->createMicroStepper(name, callbacks);
- } else {
- ERROR_EXECUTION_THROW("No Microstepper '" + name + "' known");
- }
-
- return std::shared_ptr<MicroStepImpl>();
+ if (_microSteppers.find(name) != _microSteppers.end()) {
+ std::shared_ptr<MicroStepImpl> microStepper = _microSteppers[name]->create(callbacks);
+ return microStepper;
+ }
+
+ if (_parentFactory) {
+ return _parentFactory->createMicroStepper(name, callbacks);
+ } else {
+ ERROR_EXECUTION_THROW("No Microstepper '" + name + "' known");
+ }
+
+ return std::shared_ptr<MicroStepImpl>();
}
#endif
-
+
void DataModelImpl::addExtension(DataModelExtension* ext) {
ERROR_EXECUTION_THROW("DataModel does not support extensions");
}
diff --git a/src/uscxml/plugins/Factory.h b/src/uscxml/plugins/Factory.h
index 986ff5f..cd7a5c7 100644
--- a/src/uscxml/plugins/Factory.h
+++ b/src/uscxml/plugins/Factory.h
@@ -53,31 +53,31 @@ public:
Factory(const std::string& pluginPath, Factory* parentFactory);
void registerIOProcessor(IOProcessorImpl* ioProcessor);
- bool hasIOProcessor(const std::string& type);
- std::shared_ptr<IOProcessorImpl> createIOProcessor(const std::string& type, IOProcessorCallbacks* callbacks);
+ bool hasIOProcessor(const std::string& type);
+ std::shared_ptr<IOProcessorImpl> createIOProcessor(const std::string& type, IOProcessorCallbacks* callbacks);
- void registerDataModel(DataModelImpl* dataModel);
- bool hasDataModel(const std::string& type);
- std::shared_ptr<DataModelImpl> createDataModel(const std::string& type, DataModelCallbacks* callbacks);
+ void registerDataModel(DataModelImpl* dataModel);
+ bool hasDataModel(const std::string& type);
+ std::shared_ptr<DataModelImpl> createDataModel(const std::string& type, DataModelCallbacks* callbacks);
- void registerInvoker(InvokerImpl* invoker);
- bool hasInvoker(const std::string& type);
- std::shared_ptr<InvokerImpl> createInvoker(const std::string& type, InvokerCallbacks* interpreter);
+ void registerInvoker(InvokerImpl* invoker);
+ bool hasInvoker(const std::string& type);
+ std::shared_ptr<InvokerImpl> createInvoker(const std::string& type, InvokerCallbacks* interpreter);
- void registerExecutableContent(ExecutableContentImpl* executableContent);
- bool hasExecutableContent(const std::string& localName, const std::string& nameSpace);
- std::shared_ptr<ExecutableContentImpl> createExecutableContent(const std::string& localName, const std::string& nameSpace, InterpreterImpl* interpreter);
+ void registerExecutableContent(ExecutableContentImpl* executableContent);
+ bool hasExecutableContent(const std::string& localName, const std::string& nameSpace);
+ std::shared_ptr<ExecutableContentImpl> createExecutableContent(const std::string& localName, const std::string& nameSpace, InterpreterImpl* interpreter);
#ifndef FEATS_ON_CMD
- void registerMicrostepper(MicroStepImpl* microStepper);
- bool hasMicroStepper(const std::string& name);
- std::shared_ptr<MicroStepImpl> createMicroStepper(const std::string& name, MicroStepCallbacks* callbacks);
+ void registerMicrostepper(MicroStepImpl* microStepper);
+ bool hasMicroStepper(const std::string& name);
+ std::shared_ptr<MicroStepImpl> createMicroStepper(const std::string& name, MicroStepCallbacks* callbacks);
#endif
- std::map<std::string, IOProcessorImpl*> getIOProcessors();
+ std::map<std::string, IOProcessorImpl*> getIOProcessors();
void listComponents();
@@ -96,7 +96,7 @@ protected:
std::map<std::pair<std::string, std::string>, ExecutableContentImpl*> _executableContent;
#ifndef FEATS_ON_CMD
- std::map<std::string, MicroStepImpl*> _microSteppers;
+ std::map<std::string, MicroStepImpl*> _microSteppers;
#endif
#ifdef BUILD_AS_PLUGINS
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp
index 0f64ad6..a52cf5e 100644
--- a/src/uscxml/transform/ChartToC.cpp
+++ b/src/uscxml/transform/ChartToC.cpp
@@ -54,7 +54,7 @@ ChartToC::ChartToC(const Interpreter& other) : TransformerImpl(other), _topMostM
_hasNativeDataModel = HAS_ATTR(_scxml, kXMLCharDataModel) && ATTR(_scxml, kXMLCharDataModel) == "native";
findNestedMachines();
- prepare();
+ prepare();
if (_extensions.find("prefix") != _extensions.end()) {
_prefixes = new std::list<std::string>();
@@ -382,13 +382,13 @@ void ChartToC::prepare() {
setStateCompletion();
// how many bits do we need to represent the state array?
- size_t largestStateSpace = 0;
- size_t largestTransSpace = 0;
- for (auto machine : _allMachines) {
- largestStateSpace = (machine->_states.size() > largestStateSpace ? machine->_states.size() : largestStateSpace);
- largestTransSpace = (machine->_transitions.size() > largestTransSpace ? machine->_transitions.size() : largestTransSpace);
- }
-
+ size_t largestStateSpace = 0;
+ size_t largestTransSpace = 0;
+ for (auto machine : _allMachines) {
+ largestStateSpace = (machine->_states.size() > largestStateSpace ? machine->_states.size() : largestStateSpace);
+ largestTransSpace = (machine->_transitions.size() > largestTransSpace ? machine->_transitions.size() : largestTransSpace);
+ }
+
std::string seperator;
_stateCharArraySize = ceil((float)largestStateSpace / (float)8);
_stateCharArrayInit = "{";
@@ -1670,13 +1670,13 @@ void ChartToC::writeElementInfo(std::ostream& stream) {
size_t i = 0;
for (auto iter = params.begin(); iter != params.end(); iter++, i++) {
DOMElement* param = *iter;
- // TODO: Index is wrong for multiple params!
+ // TODO: Index is wrong for multiple params!
if (param->getParentNode() != parent) {
if (i > 0) {
stream << " { NULL, NULL, NULL }," << std::endl;
- i++;
+ i++;
}
- static_cast<DOMElement*>(param->getParentNode())->setAttribute(X("paramIndex"), X(toStr(i)));
+ static_cast<DOMElement*>(param->getParentNode())->setAttribute(X("paramIndex"), X(toStr(i)));
parent = param->getParentNode();
}
stream << " { ";
diff --git a/src/uscxml/util/DOM.h b/src/uscxml/util/DOM.h
index 74133e8..2adc675 100644
--- a/src/uscxml/util/DOM.h
+++ b/src/uscxml/util/DOM.h
@@ -212,6 +212,10 @@ public :
_deallocOther = true;
}
+ bool operator==(const XMLCh* other) const {
+ return XERCESC_NS::XMLString::compareString(other, _unicodeForm) == 0;
+ }
+
bool operator==(const X& other) const {
return (_unicodeForm == other._unicodeForm) != 0;
}