diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2012-12-22 13:03:02 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2012-12-22 13:03:02 (GMT) |
commit | fa05389f050004a14787cd7b4ebb6e0b54e0e4af (patch) | |
tree | a5a97597cd48971540598e92ac14f15cd2ea6ef5 /src/uscxml | |
parent | 4b345063582d4ac89a68a053a27552a688e3a583 (diff) | |
download | uscxml-fa05389f050004a14787cd7b4ebb6e0b54e0e4af.zip uscxml-fa05389f050004a14787cd7b4ebb6e0b54e0e4af.tar.gz uscxml-fa05389f050004a14787cd7b4ebb6e0b54e0e4af.tar.bz2 |
Got rid of xpath on critical path
Improves performance by a factor of 8!
Diffstat (limited to 'src/uscxml')
-rw-r--r-- | src/uscxml/Interpreter.cpp | 55 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 171 |
2 files changed, 46 insertions, 180 deletions
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 0c4f98f..70ae623 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -856,6 +856,15 @@ Arabica::XPath::NodeSet<std::string> Interpreter::selectEventlessTransitions() { NodeSet<std::string> ancestors = getProperAncestors(atomicStates[i], Arabica::DOM::Node<std::string>()); ancestors.push_back(atomicStates[i]); for (unsigned int j = 0; j < ancestors.size(); j++) { + NodeSet<std::string> transitions = filterChildElements("transition", ancestors[j]); + for (unsigned int k = 0; k < transitions.size(); k++) { + if (!((Arabica::DOM::Element<std::string>)transitions[k]).hasAttribute("event") && hasConditionMatch(transitions[k])) { + enabledTransitions.push_back(transitions[k]); + goto LOOP; + } + } + +#if 0 NodeSet<std::string> transitions = _xpath.evaluate("" + _nsPrefix + "transition", ancestors[j]).asNodeSet(); for (unsigned int k = 0; k < transitions.size(); k++) { if (!((Arabica::DOM::Element<std::string>)transitions[k]).hasAttribute("event") && hasConditionMatch(transitions[k])) { @@ -863,6 +872,7 @@ Arabica::XPath::NodeSet<std::string> Interpreter::selectEventlessTransitions() { goto LOOP; } } +#endif } LOOP: ; @@ -1186,9 +1196,9 @@ void Interpreter::exitStates(const Arabica::XPath::NodeSet<std::string>& enabled statesToExit.reverse(); for (int i = 0; i < statesToExit.size(); i++) { - NodeSet<std::string> historyElems = _xpath.evaluate("" + _nsPrefix + "history", statesToExit[i]).asNodeSet(); - for (int j = 0; j < historyElems.size(); j++) { - Arabica::DOM::Element<std::string> historyElem = (Arabica::DOM::Element<std::string>)historyElems[j]; + NodeSet<std::string> histories = filterChildElements("history", statesToExit[i]); + for (int j = 0; j < histories.size(); j++) { + Arabica::DOM::Element<std::string> historyElem = (Arabica::DOM::Element<std::string>)histories[j]; std::string historyType = (historyElem.hasAttribute("type") ? historyElem.getAttribute("type") : "shallow"); NodeSet<std::string> historyNodes; for (int k = 0; k < _configuration.size(); k++) { @@ -1205,13 +1215,15 @@ void Interpreter::exitStates(const Arabica::XPath::NodeSet<std::string>& enabled } for (int i = 0; i < statesToExit.size(); i++) { - Arabica::XPath::NodeSet<std::string> onExitElems = _xpath.evaluate("" + _nsPrefix + "onexit", statesToExit[i]).asNodeSet(); - for (int j = 0; j < onExitElems.size(); j++) { - executeContent(onExitElems[j]); + NodeSet<std::string> onExits = filterChildElements("onExit", statesToExit[i]); + for (int j = 0; j < onExits.size(); j++) { + Arabica::DOM::Element<std::string> onExitElem = (Arabica::DOM::Element<std::string>)onExits[j]; + executeContent(onExitElem); } - Arabica::XPath::NodeSet<std::string> invokeElems = _xpath.evaluate("" + _nsPrefix + "invoke", statesToExit[i]).asNodeSet(); - for (int j = 0; j < invokeElems.size(); j++) { - cancelInvoke(invokeElems[j]); + NodeSet<std::string> invokes = filterChildElements("invoke", statesToExit[i]); + for (int j = 0; j < invokes.size(); j++) { + Arabica::DOM::Element<std::string> invokeElem = (Arabica::DOM::Element<std::string>)invokes[j]; + cancelInvoke(invokeElem); } } @@ -1299,9 +1311,9 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet<std::string>& enable _configuration.push_back(stateElem); _statesToInvoke.push_back(stateElem); if (_binding == LATE && stateElem.getAttribute("isFirstEntry").size() > 0) { - Arabica::XPath::NodeSet<std::string> dataModelElems = _xpath.evaluate("" + _nsPrefix + "datamodel", stateElem).asNodeSet(); + NodeSet<std::string> dataModelElems = filterChildElements("datamodel", stateElem); if(dataModelElems.size() > 0 && _dataModel) { - Arabica::XPath::NodeSet<std::string> dataElems = _xpath.evaluate("" + _nsPrefix + "data", dataModelElems[0]).asNodeSet(); + Arabica::XPath::NodeSet<std::string> dataElems = filterChildElements("data", dataModelElems[0]); for (int j = 0; j < dataElems.size(); j++) { initializeData(dataElems[j]); } @@ -1309,7 +1321,7 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet<std::string>& enable stateElem.setAttribute("isFirstEntry", ""); } // execute onentry executable content - Arabica::XPath::NodeSet<std::string> onEntryElems = _xpath.evaluate("" + _nsPrefix + "onentry", stateElem).asNodeSet(); + NodeSet<std::string> onEntryElems = filterChildElements("onEntry", stateElem); for (int j = 0; j < onEntryElems.size(); j++) { executeContent(onEntryElems[j]); } @@ -1468,8 +1480,12 @@ NEXT_ANCESTOR: } Arabica::DOM::Node<std::string> Interpreter::getState(const std::string& stateId) { + + if (_cachedStates.find(stateId) != _cachedStates.end()) { + return _cachedStates[stateId]; + } + // first try atomic and compund states -// std::cout << _nsPrefix << stateId << std::endl; NodeSet<std::string> target = _xpath.evaluate("//" + _nsPrefix + "state[@id='" + stateId + "']", _doc).asNodeSet(); if (target.size() > 0) goto FOUND; @@ -1487,6 +1503,7 @@ Arabica::DOM::Node<std::string> Interpreter::getState(const std::string& stateId FOUND: if (target.size() > 0) { assert(target.size() == 1); + _cachedStates[stateId] = target[0]; return target[0]; } // return the empty node @@ -1575,6 +1592,18 @@ std::vector<std::string> Interpreter::tokenizeIdRefs(const std::string& idRefs) return ids; } +NodeSet<std::string> Interpreter::filterChildElements(const std::string& tagName, const Node<std::string>& node) { + NodeSet<std::string> filteredChildElems; + NodeList<std::string> childs = node.getChildNodes(); + for (unsigned int i = 0; i < childs.getLength(); i++) { + if (childs.item(i).getNodeType() != Node_base::ELEMENT_NODE || + !boost::iequals(TAGNAME(childs.item(i)), tagName)) + continue; + filteredChildElems.push_back(childs.item(i)); + } + return filteredChildElems; +} + NodeSet<std::string> Interpreter::getProperAncestors(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2) { NodeSet<std::string> ancestors; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 58b2a51..b723b5f 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -188,7 +188,8 @@ protected: bool parentIsScxmlState(Arabica::DOM::Node<std::string> state); static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs); - + static Arabica::XPath::NodeSet<std::string> filterChildElements(const std::string& tagname, const Arabica::DOM::Node<std::string>& node); + static boost::uuids::random_generator uuidGen; static const std::string getUUID(); @@ -203,174 +204,10 @@ protected: std::map<std::string, Invoker*> _invokerIds; std::map<std::string, Invoker*> _invokers; + /// We need to remember to adapt them when the DOM is operated upon + std::map<std::string, Arabica::DOM::Node<std::string> > _cachedStates; }; -#if 0 -class SCXMLParseHandler : - public Arabica::SAX::EntityResolver<std::string>, - public Arabica::SAX::DTDHandler<std::string>, - public Arabica::SAX::ContentHandler<std::string>, - public Arabica::SAX::CatchErrorHandler<std::string>, - public Arabica::SAX::LexicalHandler<std::string>, - public Arabica::SAX::DeclHandler<std::string> { -public: - SCXMLParseHandler() { } - virtual ~SCXMLParseHandler() { } - - // EntityResolver - virtual InputSourceT resolveEntity(const std::string& publicId , const std::string& systemId) { - return InputSourceT(); - } - - // DTDHandler - virtual void notationDecl(const std::string& name, - const std::string& publicId, - const std::string& systemId) { - std::cout << "notationDecl" << std::endl; - std::cout << " name:" << name << std::endl; - std::cout << " publicId:" << publicId << std::endl; - std::cout << " systemId:" << systemId << std::endl; - } - virtual void unparsedEntityDecl(const std::string& name, - const std::string& publicId, - const std::string& systemId, - const std::string& notationName) { - std::cout << "unparsedEntityDecl" << std::endl; - std::cout << " name:" << name << std::endl; - std::cout << " publicId:" << publicId << std::endl; - std::cout << " systemId:" << systemId << std::endl; - std::cout << " notationName:" << notationName << std::endl; - } - - // ContentHandler - virtual void setDocumentLocator(const LocatorT& locator) { - std::cout << "setDocumentLocator" << std::endl; - } - virtual void startDocument() { - std::cout << "startDocument" << std::endl; - } - virtual void endDocument() { - std::cout << "endDocument" << std::endl; - } - virtual void startPrefixMapping(const std::string& prefix, const std::string& uri) { - std::cout << "startPrefixMapping" << std::endl; - std::cout << " prefix:" << prefix << std::endl; - std::cout << " uri:" << uri << std::endl; - } - virtual void endPrefixMapping(const std::string& prefix) { - std::cout << "endPrefixMapping" << std::endl; - std::cout << " prefix:" << prefix << std::endl; - } - virtual void startElement(const std::string& namespaceURI, const std::string& localName, - const std::string& qName, const AttributesT& atts) { - std::cout << "startElement" << std::endl; - std::cout << " namespaceURI:" << namespaceURI << std::endl; - std::cout << " localName:" << localName << std::endl; - std::cout << " qName:" << qName << std::endl; - std::cout << " atts:" << atts.getLength() << std::endl; - } - virtual void endElement(const std::string& namespaceURI, const std::string& localName, - const std::string& qName) { - std::cout << "endElement" << std::endl; - std::cout << " namespaceURI:" << namespaceURI << std::endl; - std::cout << " localName:" << localName << std::endl; - std::cout << " qName:" << qName << std::endl; - } - virtual void characters(const std::string& ch) { - std::cout << "characters" << std::endl; - std::cout << " ch:" << ch << std::endl; - } - virtual void ignorableWhitespace(const std::string& ch) { - std::cout << "ignorableWhitespace" << std::endl; - std::cout << " ch:" << ch << std::endl; - } - virtual void processingInstruction(const std::string& target, const std::string& data) { - std::cout << "processingInstruction" << std::endl; - std::cout << " target:" << target << std::endl; - std::cout << " data:" << data << std::endl; - } - virtual void skippedEntity(const std::string& name) { - std::cout << "skippedEntity" << std::endl; - std::cout << " name:" << name << std::endl; - } - - // ErrorHandler - virtual void warning(const SAXParseExceptionT& e) { - Arabica::SAX::CatchErrorHandler<std::string>::warning(e); - } - virtual void error(const SAXParseExceptionT& e) { - Arabica::SAX::CatchErrorHandler<std::string>::error(e); - } - virtual void fatalError(const SAXParseExceptionT& e) { - Arabica::SAX::CatchErrorHandler<std::string>::fatalError(e); - } - - // LexicalHandler - virtual void startDTD(const std::string& name, - const std::string& publicId, - const std::string& systemId) { - std::cout << "startDTD" << std::endl; - std::cout << " name:" << name << std::endl; - std::cout << " publicId:" << publicId << std::endl; - std::cout << " systemId:" << systemId << std::endl; - } - - virtual void endDTD() { - std::cout << "endDTD" << std::endl; - } - virtual void startEntity(const std::string& name) { - std::cout << "startEntity" << std::endl; - std::cout << " name:" << name << std::endl; - } - virtual void endEntity(const std::string& name) { - std::cout << "endEntity" << std::endl; - std::cout << " name:" << name << std::endl; - } - virtual void startCDATA() { - std::cout << "startCDATA" << std::endl; - } - virtual void endCDATA() { - std::cout << "endCDATA" << std::endl; - } - virtual void comment(const std::string& text) { - std::cout << "comment" << std::endl; - std::cout << " text:" << text << std::endl; - } - - // DeclHandler - virtual void elementDecl(const std::string& name, const std::string& model) { - std::cout << "elementDecl" << std::endl; - std::cout << " name:" << name << std::endl; - std::cout << " model:" << model << std::endl; - } - virtual void attributeDecl(const std::string& elementName, - const std::string& attributeName, - const std::string& type, - const std::string& valueDefault, - const std::string& value) { - std::cout << "attributeDecl" << std::endl; - std::cout << " elementName:" << elementName << std::endl; - std::cout << " attributeName:" << attributeName << std::endl; - std::cout << " type:" << type << std::endl; - std::cout << " valueDefault:" << valueDefault << std::endl; - std::cout << " value:" << value << std::endl; - } - virtual void internalEntityDecl(const std::string& name, const std::string& value) { - std::cout << "internalEntityDecl" << std::endl; - std::cout << " name:" << name << std::endl; - std::cout << " value:" << value << std::endl; - } - virtual void externalEntityDecl(const std::string& name, - const std::string& publicId, - const std::string& systemId) { - std::cout << "externalEntityDecl" << std::endl; - std::cout << " name:" << name << std::endl; - std::cout << " publicId:" << publicId << std::endl; - std::cout << " systemId:" << systemId << std::endl; - } - -}; -#endif } #endif |