summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp')
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp180
1 files changed, 121 insertions, 59 deletions
diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
index 62f7a1e..4d3c579 100644
--- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
@@ -18,16 +18,22 @@
*/
#include "USCXMLInvoker.h"
-#include <glog/logging.h>
-#include "uscxml/dom/DOMUtils.h"
-#include <DOM/SAX2DOM/SAX2DOM.hpp>
+
+#include "uscxml/config.h"
#ifdef BUILD_AS_PLUGINS
#include <Pluma/Connector.hpp>
#endif
+#ifdef UNIX
+#include <pthread.h>
+#endif
+
namespace uscxml {
+// msxml.h should die in a fire for polluting the global namespace
+// using namespace xercesc;
+
#ifdef BUILD_AS_PLUGINS
PLUMA_CONNECTOR
bool pluginConnect(pluma::Host& host) {
@@ -36,26 +42,88 @@ bool pluginConnect(pluma::Host& host) {
}
#endif
-USCXMLInvoker::USCXMLInvoker() : _cancelled(false) {
- _parentQueue._invoker = this;
+USCXMLInvoker::USCXMLInvoker() {
+ _parentQueue = EventQueue(std::shared_ptr<ParentQueueImpl>(new ParentQueueImpl(this)));
+ _thread = NULL;
+ _isActive = false;
+ _isStarted = false;
}
USCXMLInvoker::~USCXMLInvoker() {
+ stop();
};
+void USCXMLInvoker::start() {
+ _isStarted = true;
+ _thread = new std::thread(USCXMLInvoker::run, this);
+}
+
+void USCXMLInvoker::stop() {
+ _isStarted = false;
+ _isActive = false;
+
+ if (_thread) {
+ /**
+ * We cannot join the invoked thread if it is blocking at an external
+ * receive. Cancel will finalize and unblock.
+ */
+ _invokedInterpreter.cancel();
+ _thread->join();
+ delete _thread;
+ _thread = NULL;
+ }
+}
+
void USCXMLInvoker::uninvoke() {
- _cancelled = true;
- Event event;
- event.name = "unblock.and.die";
- if (_invokedInterpreter)
+ _isActive = false;
+ stop();
+}
+
+void USCXMLInvoker::eventFromSCXML(const Event& event) {
+ if (_isActive) {
_invokedInterpreter.receive(event);
+ }
+}
+
+void USCXMLInvoker::run(void* instance) {
+ USCXMLInvoker* INSTANCE = (USCXMLInvoker*)instance;
+
+#ifdef APPLE
+ std::string threadName;
+ threadName += "uscxml::";
+ threadName += (INSTANCE->_invokedInterpreter.getImpl()->_name.size() > 0 ? INSTANCE->_invokedInterpreter.getImpl()->_name : "anon");
+ threadName += ".scxml";
+
+ pthread_setname_np(threadName.c_str());
+#endif
+ InterpreterState state = USCXML_UNDEF;
+ while(state != USCXML_FINISHED) {
+ state = INSTANCE->_invokedInterpreter.step(true);
+
+// if (!INSTANCE->_isStarted) {
+// // we have been cancelled
+// INSTANCE->_isActive = false;
+// return;
+// }
+ }
+
+ if (INSTANCE->_isActive) {
+ // we finished on our own and were not cancelled
+ Event e;
+ e.eventType = Event::PLATFORM;
+ e.invokeid = INSTANCE->_invokedInterpreter.getImpl()->getInvokeId();
+ e.name = "done.invoke." + e.invokeid;
+ INSTANCE->_interpreter->enqueueExternal(e);
+ }
+
+ INSTANCE->_isActive = false;
}
-boost::shared_ptr<InvokerImpl> USCXMLInvoker::create(InterpreterImpl* interpreter) {
- boost::shared_ptr<USCXMLInvoker> invoker = boost::shared_ptr<USCXMLInvoker>(new USCXMLInvoker());
- invoker->_parentInterpreter = interpreter;
+std::shared_ptr<InvokerImpl> USCXMLInvoker::create(InterpreterImpl* interpreter) {
+ std::shared_ptr<USCXMLInvoker> invoker(new USCXMLInvoker());
+ invoker->_interpreter = interpreter;
return invoker;
}
@@ -64,71 +132,65 @@ Data USCXMLInvoker::getDataModelVariables() {
return data;
}
-void USCXMLInvoker::send(const SendRequest& req) {
- if (_invokedInterpreter)
- _invokedInterpreter.receive(req);
-}
-
-void USCXMLInvoker::cancel(const std::string sendId) {
- assert(false);
-}
+void USCXMLInvoker::invoke(const std::string& source, const Event& invokeEvent) {
+ if (source.length() > 0) {
+ _invokedInterpreter = Interpreter::fromURL(source);
+ } else if (invokeEvent.data.node) {
+ xercesc::DOMImplementation* implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(X("core"));
+ xercesc::DOMDocument* document = implementation->createDocument();
-void USCXMLInvoker::invoke(const InvokeRequest& req) {
- _cancelled = false;
- if (req.src.length() > 0) {
- _invokedInterpreter = Interpreter::fromURL(req.src);
- } else if (req.dom) {
- Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- Arabica::DOM::Document<std::string> dom = domFactory.createDocument(req.dom.getNamespaceURI(), "", 0);
// we need to import the parent - to support xpath test150
- Arabica::DOM::Node<std::string> newNode = dom.importNode(req.dom, true);
- dom.appendChild(newNode);
+ xercesc::DOMNode* newNode = document->importNode(invokeEvent.data.node, true);
+ document->appendChild(newNode);
+
+// std::cout << *document << std::endl;
+
// TODO: where do we get the namespace from?
- _invokedInterpreter = Interpreter::fromDOM(dom, _interpreter->getNameSpaceInfo(), _interpreter->getSourceURL());
- } else if (req.content.size() > 0) {
- _invokedInterpreter = Interpreter::fromXML(req.content, _interpreter->getSourceURL());
+ _invokedInterpreter = Interpreter::fromDocument(document, _interpreter->getBaseURL());
+
} else {
- LOG(ERROR) << "Cannot invoke nested SCXML interpreter, neither src attribute nor content nor DOM is given";
+ _isActive = false;
+ ERROR_PLATFORM_THROW("Cannot invoke nested SCXML interpreter, neither src attribute nor content nor DOM is given");
}
- if (_invokedInterpreter) {
- if (req.elem && HAS_ATTR(req.elem, "initial")) {
- _invokedInterpreter.setInitalConfiguration(tokenize(ATTR(req.elem, "initial")));
- }
- DataModel dataModel(_invokedInterpreter.getImpl()->getDataModel());
- _invokedInterpreter.getImpl()->setParentQueue(&_parentQueue);
+ if (_invokedInterpreter) {
+ _invokedInterpreter.getImpl()->_parentQueue = _parentQueue;
+ _invokedInterpreter.getImpl()->_invokeId = invokeEvent.invokeid;
+ _invokedInterpreter.getImpl()->_invokeReq = invokeEvent;
// copy monitors
- std::set<InterpreterMonitor*>::const_iterator monIter = _interpreter->_monitors.begin();
- while(monIter != _interpreter->_monitors.end()) {
- if ((*monIter)->copyToInvokers()) {
- _invokedInterpreter.getImpl()->_monitors.insert(*monIter);
- }
- monIter++;
- }
-
- // transfer namespace prefixes
- _invokedInterpreter.setNameSpaceInfo(_parentInterpreter->getNameSpaceInfo());
- _invokedInterpreter.getImpl()->_sessionId = req.invokeid;
+// std::set<InterpreterMonitor*>::const_iterator monIter = _interpreter->_monitors.begin();
+// while(monIter != _interpreter->_monitors.end()) {
+// if ((*monIter)->copyToInvokers()) {
+// _invokedInterpreter.getImpl()->_monitors.insert(*monIter);
+// }
+// monIter++;
+// }
+
/// test240 assumes that invoke request params will carry over to the datamodel
- _invokedInterpreter.getImpl()->setInvokeRequest(req);
+// _invokedInterpreter.getImpl()->setInvokeRequest(req);
+ _isActive = true;
+
+ // we need to make sure it is at least setup to receive data!
+ _invokedInterpreter.getImpl()->init();
+
+ start();
- _invokedInterpreter.start();
} else {
/// test 530
- _parentInterpreter->receive(Event("done.invoke." + _invokeId, Event::PLATFORM));
+ Event e("done.invoke." + invokeEvent.invokeid, Event::PLATFORM);
+ eventToSCXML(e, USCXML_INVOKER_SCXML_TYPE, _invokeId);
+ _isActive = false;
}
}
-void USCXMLInvoker::ParentQueue::push(const SendRequest& event) {
+void USCXMLInvoker::ParentQueueImpl::enqueue(const Event& event) {
// test 252
- if (_invoker->_cancelled)
+ if (!_invoker->_isActive)
return;
- SendRequest copyEvent(event);
- // this is somewhat hidden here!
- copyEvent.invokeid = _invoker->_invokeId;
- _invoker->_parentInterpreter->receive(copyEvent);
+ Event copy(event); // TODO: can we get around a copy?
+ _invoker->eventToSCXML(copy, USCXML_INVOKER_SCXML_TYPE, _invoker->_invokeId);
}
} \ No newline at end of file