diff options
author | Stefan Radomski <github@mintwerk.de> | 2016-05-12 13:12:33 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2016-05-12 13:12:33 (GMT) |
commit | b62e7979600feee23dc7cdb61042a8fc7673122b (patch) | |
tree | f7351372f37979dd2d048e0b68a16a4cd3b2aadb /test/src/test-c-machine.cpp | |
parent | 1b11b310be61e51b3ac5ebb83f7c8a33aef3d6e8 (diff) | |
download | uscxml-b62e7979600feee23dc7cdb61042a8fc7673122b.zip uscxml-b62e7979600feee23dc7cdb61042a8fc7673122b.tar.gz uscxml-b62e7979600feee23dc7cdb61042a8fc7673122b.tar.bz2 |
Major Refactoring v2.0
Diffstat (limited to 'test/src/test-c-machine.cpp')
-rw-r--r-- | test/src/test-c-machine.cpp | 981 |
1 files changed, 0 insertions, 981 deletions
diff --git a/test/src/test-c-machine.cpp b/test/src/test-c-machine.cpp deleted file mode 100644 index 9ee3f1f..0000000 --- a/test/src/test-c-machine.cpp +++ /dev/null @@ -1,981 +0,0 @@ -#include <string.h> -#include <stdlib.h> // malloc -#include <assert.h> // assert -#include <stdio.h> // printf -#include <sstream> // stringstream -#include <deque> // deque -#include <boost/algorithm/string.hpp> // trim - -#define USCXML_VERBOSE - -#include "uscxml/config.h" - -#ifdef APPLE -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <pthread.h> -#endif - -#ifndef AUTOINCLUDE_TEST -#include "test-c-machine.scxml.c" -#endif - -#include "uscxml/Convenience.h" -#include "uscxml/URL.h" -#include "uscxml/concurrency/Timer.h" -//#include "uscxml/dom/DOMUtils.h" -#include "uscxml/Factory.h" -//#include "uscxml/Interpreter.h" -#include "uscxml/UUID.h" - -#include "uscxml/concurrency/DelayedEventQueue.h" -#include "uscxml/concurrency/tinythread.h" - -#ifdef BUILD_PROFILING -# include "uscxml/plugins/DataModel.h" -# endif - -#define USER_DATA(ctx) ((StateMachine*)(((uscxml_ctx*)ctx)->user_data)) - -using namespace uscxml; - -class StateMachine : public InterpreterInfo { -public: - StateMachine(const uscxml_machine* machine) : machine(machine), parentMachine(NULL), topMostMachine(NULL), invocation(NULL) { - allMachines[sessionId] = this; - topMostMachine = this; - currentMachine = allMachines.begin(); - init(); - } - - StateMachine(StateMachine* parent, const uscxml_machine* machine, const uscxml_elem_invoke* invoke) : machine(machine), invocation(invoke) { - parentMachine = parent; - topMostMachine = parent->topMostMachine; - init(); - } - - void init() { - sessionId = UUID::getUUID(); - isFinalized = false; - currEvent = NULL; - - // clear and initialize machine context - memset(&ctx, 0, sizeof(uscxml_ctx)); - ctx.machine = machine; - ctx.user_data = (void*)this; - - // register callbacks with scxml context - ctx.is_matched = &isMatched; - ctx.is_true = &isTrue; - ctx.raise_done_event = &raiseDoneEvent; - ctx.invoke = &invoke; - ctx.exec_content_send = &execContentSend; - ctx.exec_content_raise = &execContentRaise; - ctx.exec_content_cancel = &execContentCancel; - ctx.exec_content_log = &execContentLog; - ctx.exec_content_assign = &execContentAssign; - ctx.exec_content_foreach_init = &execContentForeachInit; - ctx.exec_content_foreach_next = &execContentForeachNext; - ctx.exec_content_foreach_done = &execContentForeachDone; - ctx.dequeue_external = &dequeueExternal; - ctx.dequeue_internal = &dequeueInternal; - ctx.exec_content_init = &execContentInit; - ctx.exec_content_script = &execContentScript; - - name = machine->name; - - delayQueue.start(); - dataModel = Factory::getInstance()->createDataModel(machine->datamodel, this); - - if (invocation != NULL) { - /// test 226/240 - initialize from invoke request - if (invocation->params != NULL) { - const uscxml_elem_param* param = invocation->params; - while(USCXML_ELEM_PARAM_IS_SET(param)) { - std::string identifier; - if (param->name != NULL) { - identifier = param->name; - } else if (param->location != NULL) { - identifier = param->location; - } - invokeData[identifier] = parentMachine->dataModel.getStringAsData(param->expr); - param++; - } - } - - if (invocation->namelist != NULL) { - const char* cPtr = invocation->namelist; - const char* aPtr = invocation->namelist; - while(cPtr) { - while (isspace(*cPtr)) - cPtr++; - aPtr = cPtr; - while(*cPtr && !isspace(*cPtr)) - cPtr++; - - if (aPtr == cPtr) - break; - - std::string identifier = std::string(aPtr, cPtr - aPtr); - invokeData[identifier] = parentMachine->dataModel.getStringAsData(identifier); - } - } - } - } - - virtual ~StateMachine() { - if (parentMachine != NULL) { - topMostMachine->allMachines.erase(topMostMachine->invocationIds[invocation]); - } -// finalize(); - - delayQueue.stop(); - delayQueue.cancelAllEvents(); - - while(eq.size() > 0) { - delete eq.front(); - eq.pop_front(); - } - eq.clear(); - while(iq.size() > 0) { - delete iq.front(); - iq.pop_front(); - } - iq.clear(); - } - - bool hasPendingWork() { - return (iq.size() > 0 || - eq.size() > 0 || - ctx.flags & USCXML_CTX_SPONTANEOUS || - ctx.flags == USCXML_CTX_PRISTINE || - memcmp(ctx.config, ctx.invocations, sizeof(ctx.config)) != 0); - } - - bool isDone() { - return ctx.flags & USCXML_CTX_FINISHED; - } - - void finalize() { - if (isFinalized) - return; - - delayQueue.stop(); - delayQueue.cancelAllEvents(); - - if (parentMachine != NULL) { - tthread::lock_guard<tthread::mutex> lock(mutex); - - Event* done = new Event(); - done->invokeid = invokeId; - done->name = "done.invoke." + invokeId; - parentMachine->eq.push_back(done); - } - isFinalized = true; - } - - void reset() { - delayQueue.stop(); - delayQueue.cancelAllEvents(); - - while(eq.size() > 0) { - delete eq.front(); - eq.pop_front(); - } - while(iq.size() > 0) { - delete iq.front(); - iq.pop_front(); - } - - iq.clear(); - eq.clear(); - - init(); - - } - - int step() { - // advance current machine if there are multiple - currentMachine++; - if (currentMachine == allMachines.end()) - currentMachine = allMachines.begin(); - - StateMachine* toRun = currentMachine->second; - if (!toRun->hasPendingWork()) { - return USCXML_ERR_IDLE; - } - - // test 187 - if (toRun->isDone()) { - toRun->finalize(); - return USCXML_ERR_IDLE; - } - - state = uscxml_step(&toRun->ctx); - if (toRun->currEvent != NULL) { - delete toRun->currEvent; - toRun->currEvent = NULL; - } - - return state; - } - - // InterpreterInfo - NameSpaceInfo getNameSpaceInfo() const { - return nsInfo; - } - const std::string& getName() { - return name; - } - const std::string& getSessionId() { - return sessionId; - } - const std::map<std::string, IOProcessor>& getIOProcessors() { - return ioProcs; - } - const std::map<std::string, Invoker>& getInvokers() { - return invokers; - } - Arabica::DOM::Document<std::string> getDocument() const { - return document; - } - - bool isInState(const std::string& stateId) { - for (size_t i = 0 ; i < ctx.machine->nr_states; i++) { - if (ctx.machine->states[i].name != NULL && BIT_HAS(i, ctx.config) && stateId == ctx.machine->states[i].name) - return true; - } - return false; - } - - // callbacks for scxml context - - static int isMatched(const uscxml_ctx* ctx, const uscxml_transition* t, const void* e) { - Event* event = (Event*)e; - return (nameMatch(t->event, event->name.c_str())); - } - - static int isTrue(const uscxml_ctx* ctx, const char* expr) { - try { - return USER_DATA(ctx)->dataModel.evalAsBool(expr); - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - } - return false; - } - - static int invoke(const uscxml_ctx* ctx, const uscxml_state* s, const uscxml_elem_invoke* invocation, unsigned char uninvoke) { - std::map<std::string, StateMachine*> &allMachines = USER_DATA(ctx)->topMostMachine->allMachines; - StateMachine* topMachine = USER_DATA(ctx)->topMostMachine; - - if (uninvoke) { - if (invocation->machine != NULL) { - if (topMachine->invocationIds.find(invocation) != topMachine->invocationIds.end() && - allMachines.find(topMachine->invocationIds[invocation]) != allMachines.end()) { - - delete allMachines[topMachine->invocationIds[invocation]]; - topMachine->allMachines.erase(topMachine->invocationIds[invocation]); - topMachine->invocationIds.erase(invocation); - } - } else { - return USCXML_ERR_UNSUPPORTED; - } - } else { - // invocations - if (invocation->machine != NULL) { - // invoke a nested SCXML machine - StateMachine* invokedMachine = NULL; - try { - invokedMachine = new StateMachine(USER_DATA(ctx), invocation->machine, invocation); - } catch (Event e) { - delete invokedMachine; - return USCXML_ERR_EXEC_CONTENT; - } - if (invocation->id != NULL) { - invokedMachine->invokeId = invocation->id; - } else if (invocation->idlocation != NULL) { - // test224 - invokedMachine->invokeId = (invocation->sourcename != NULL ? std::string(invocation->sourcename) + "." : "") + UUID::getUUID(); - USER_DATA(ctx)->dataModel.assign(invocation->idlocation, Data(invokedMachine->invokeId, Data::VERBATIM)); - } else { - delete invokedMachine; - return USCXML_ERR_UNSUPPORTED; - } - allMachines[invokedMachine->invokeId] = invokedMachine; - topMachine->invocationIds[invocation] = invokedMachine->invokeId; - } else { - return USCXML_ERR_UNSUPPORTED; - } - } - return USCXML_ERR_OK; - } - - static int raiseDoneEvent(const uscxml_ctx* ctx, const uscxml_state* state, const uscxml_elem_donedata* donedata) { - Event* e = new Event(); - e->name = std::string("done.state.") + state->name; - - if (donedata) { - if (donedata->content != NULL) { - e->data = Data(donedata->content, Data::VERBATIM); - } else if (donedata->contentexpr != NULL) { - try { - e->data = USER_DATA(ctx)->dataModel.getStringAsData(donedata->contentexpr); - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - } - } else { - try { - const uscxml_elem_param* param = donedata->params; - while (param && USCXML_ELEM_PARAM_IS_SET(param)) { - Data paramValue; - if (param->expr != NULL) { - paramValue = USER_DATA(ctx)->dataModel.getStringAsData(param->expr); - } else if(param->location) { - paramValue = USER_DATA(ctx)->dataModel.getStringAsData(param->location); - } - e->params.insert(std::make_pair(param->name, paramValue)); - param++; - } - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - } - } - } - -#ifdef USCXML_VERBOSE - printf("Raising Done Event: %s\n", e->name.c_str()); -#endif - USER_DATA(ctx)->iq.push_back(e); - return USCXML_ERR_OK; - } - - static int execContentSend(const uscxml_ctx* ctx, const uscxml_elem_send* send) { - SendRequest* e = new SendRequest(); - - std::string sendid; - if (send->id != NULL) { - sendid = send->id; - } else { - sendid = UUID::getUUID(); - if (send->idlocation != NULL) { - USER_DATA(ctx)->dataModel.assign(send->idlocation, Data(sendid, Data::VERBATIM)); - } else { - e->hideSendId = true; - } - } - e->sendid = sendid; - - std::string target; - if (send->target != NULL) { - e->target = send->target; - } else if (send->targetexpr != NULL) { - e->target = USER_DATA(ctx)->dataModel.evalAsString(send->targetexpr); - } else { - e->target = "#_external"; - } - - if (e->target.size() > 0 && (e->target[0] != '#' || e->target[1] != '_')) { - e->name = "error.execution"; - execContentRaise(ctx, e); - return USCXML_ERR_INVALID_TARGET; - } - - e->origintype = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"; - e->origin = e->target; - - try { - if (send->type != NULL) { - e->type = send->type; - } else if (send->typeexpr != NULL) { - e->type = USER_DATA(ctx)->dataModel.evalAsString(send->typeexpr); - } else { - e->type = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"; - } - } catch (Event exc) { - e->name = "error.execution"; - execContentRaise(ctx, e); - return USCXML_ERR_EXEC_CONTENT; - } - - // only one somewhat supported - if (e->type != "http://www.w3.org/TR/scxml/#SCXMLEventProcessor") { - e->name = "error.execution"; - execContentRaise(ctx, e); - return USCXML_ERR_INVALID_TARGET; - } - - e->origintype = e->type; - e->invokeid = USER_DATA(ctx)->invokeId; - - if (send->eventexpr != NULL) { - e->name = USER_DATA(ctx)->dataModel.evalAsString(send->eventexpr); - } else { - e->name = send->event; - } - - try { - const uscxml_elem_param* param = send->params; - while (param && USCXML_ELEM_PARAM_IS_SET(param)) { - Data paramValue; - if (param->expr != NULL) { - paramValue = USER_DATA(ctx)->dataModel.getStringAsData(param->expr); - } else if(param->location) { - paramValue = USER_DATA(ctx)->dataModel.getStringAsData(param->location); - } - e->params.insert(std::make_pair(param->name, paramValue)); - param++; - } - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - return USCXML_ERR_EXEC_CONTENT; - } - - try { - if (send->namelist != NULL) { - const char* bPtr = &send->namelist[0]; - const char* ePtr = bPtr; - while(*ePtr != '\0') { - ePtr++; - if (*ePtr == ' ' || *ePtr == '\0') { - std::string key(bPtr, ePtr - bPtr); - e->params.insert(std::make_pair(key, USER_DATA(ctx)->dataModel.getStringAsData(key))); - if (*ePtr == '\0') - break; - bPtr = ++ePtr; - } - } - } - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - return USCXML_ERR_EXEC_CONTENT; - } - - if (send->content != NULL) { - // will it parse as json? - Data d = Data::fromJSON(send->content); - if (!d.empty()) { - e->data = d; - } else { - e->data = Data(spaceNormalize(send->content), Data::VERBATIM); - } - } - - size_t delayMs = 0; - std::string delay; - if (send->delayexpr != NULL) { - delay = USER_DATA(ctx)->dataModel.evalAsString(send->delayexpr); - } else if (send->delay != NULL) { - delay = send->delay; - } - if (delay.size() > 0) { - boost::trim(delay); - - NumAttr delayAttr(delay); - if (iequals(delayAttr.unit, "ms")) { - delayMs = strTo<uint32_t>(delayAttr.value); - } else if (iequals(delayAttr.unit, "s")) { - delayMs = strTo<double>(delayAttr.value) * 1000; - } else if (delayAttr.unit.length() == 0) { // unit less delay is interpreted as milliseconds - delayMs = strTo<uint32_t>(delayAttr.value); - } else { - std::cerr << "Cannot make sense of delay value " << delay << ": does not end in 's' or 'ms'"; - } - } - - if (USER_DATA(ctx)->invokeId.size() > 0) { - e->invokeid = USER_DATA(ctx)->invokeId; - } - - USER_DATA(ctx)->sendIds[sendid] = e; - if (delayMs > 0) { - USER_DATA(ctx)->delayQueue.addEvent(sendid, delayedSend, delayMs, (void*)ctx); - } else { - delayedSend((void*)ctx, sendid); - } - - return USCXML_ERR_OK; - } - - static int execContentRaise(const uscxml_ctx* ctx, Event* e) { - if (boost::starts_with(e->name, "error.")) { - e->eventType = Event::PLATFORM; - } else { - e->eventType = Event::INTERNAL; - } - USER_DATA(ctx)->iq.push_back(e); - return USCXML_ERR_OK; - } - - static int execContentRaise(const uscxml_ctx* ctx, const char* event) { - Event* e = new Event(); - e->name = event; - return execContentRaise(ctx, e); - } - - static int execContentCancel(const uscxml_ctx* ctx, const char* sendid, const char* sendidexpr) { - std::string eventId; - if (sendid != NULL) { - eventId = sendid; - } else if (sendidexpr != NULL) { - eventId = USER_DATA(ctx)->dataModel.evalAsString(sendidexpr); - } - - if (eventId.length() > 0) { - USER_DATA(ctx)->delayQueue.cancelEvent(eventId); - } else { - execContentRaise(ctx, "error.execution"); - return USCXML_ERR_EXEC_CONTENT; - } - return USCXML_ERR_OK; - } - - static int execContentLog(const uscxml_ctx* ctx, const char* label, const char* expr) { - try { - if (label != NULL) { - printf("%s%s", label, (expr != NULL ? ": " : "")); - } - if (expr != NULL) { - std::string msg = USER_DATA(ctx)->dataModel.evalAsString(expr); - printf("%s", msg.c_str()); - } - if (label != NULL || expr != NULL) { - printf("\n"); - } - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - return USCXML_ERR_EXEC_CONTENT; - } - return USCXML_ERR_OK; - } - - static int execContentAssign(const uscxml_ctx* ctx, const uscxml_elem_assign* assign) { - std::string key = assign->location; - if (key == "_sessionid" || key == "_name" || key == "_ioprocessors" || key == "_invokers" || key == "_event") { - execContentRaise(ctx, "error.execution"); - return USCXML_ERR_EXEC_CONTENT; - } - - try { -// Data d = USER_DATA(ctx)->dataModel.getStringAsData(expr); - if (assign->expr != NULL) { - Data d = Data(assign->expr, Data::INTERPRETED); - USER_DATA(ctx)->dataModel.assign(key, d); - } else if (assign->content != NULL) { - Data d = Data(assign->content, Data::INTERPRETED); - USER_DATA(ctx)->dataModel.assign(key, d); - } - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - return USCXML_ERR_EXEC_CONTENT; - } - return USCXML_ERR_OK; - } - - static int execContentForeachInit(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach) { - try { - scxml_foreach_info* feInfo = (scxml_foreach_info*)malloc(sizeof(scxml_foreach_info)); - USER_DATA(ctx)->foreachInfo[foreach] = feInfo; - - feInfo->iterations = USER_DATA(ctx)->dataModel.getLength(foreach->array); - feInfo->currIteration = 0; - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - return USCXML_ERR_EXEC_CONTENT; - } - return USCXML_ERR_OK; - } - - static int execContentForeachNext(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach) { - try { - scxml_foreach_info* feInfo = USER_DATA(ctx)->foreachInfo[foreach]; - if (feInfo->currIteration < feInfo->iterations) { - USER_DATA(ctx)->dataModel.setForeach((foreach->item != NULL ? foreach->item : ""), - (foreach->array != NULL ? foreach->array : ""), - (foreach->index != NULL ? foreach->index : ""), - feInfo->currIteration); - feInfo->currIteration++; - return USCXML_ERR_OK; - } - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - free(USER_DATA(ctx)->foreachInfo[foreach]); - USER_DATA(ctx)->foreachInfo.erase(foreach); - return USCXML_ERR_EXEC_CONTENT; - } - return USCXML_ERR_FOREACH_DONE; - } - - static int execContentForeachDone(const uscxml_ctx* ctx, const uscxml_elem_foreach* foreach) { - free(USER_DATA(ctx)->foreachInfo[foreach]); - USER_DATA(ctx)->foreachInfo.erase(foreach); - return USCXML_ERR_OK; - } - - static int execContentInit(const uscxml_ctx* ctx, const uscxml_elem_data* data) { - while(USCXML_ELEM_DATA_IS_SET(data)) { - if (USER_DATA(ctx)->invokeData.find(data->id) != USER_DATA(ctx)->invokeData.end()) { - // passed via param or namelist: test245 - try { - USER_DATA(ctx)->dataModel.init(data->id, USER_DATA(ctx)->invokeData[data->id]); - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - } - } else { - Data d; - std::stringstream content; - - try { - if (data->expr != NULL) { - d = Data(data->expr, Data::INTERPRETED); - - } else if (data->content != NULL || data->src != NULL) { - if (data->content) { - content << data->content; - } else { - URL sourceURL(data->src); - if (USER_DATA(ctx)->baseURL.size() > 0) { - sourceURL.toAbsolute(USER_DATA(ctx)->baseURL); - } else { - sourceURL.toAbsoluteCwd(); - } - content << sourceURL; - } - /** - * first attempt to parse as structured data, we will try - * as space normalized string literals if this fails below - */ - d = USER_DATA(ctx)->dataModel.getStringAsData(content.str()); - - } else { - d = Data("undefined", Data::INTERPRETED); - } - // this might fail with an unquoted string literal in content - USER_DATA(ctx)->dataModel.init(data->id, d); - - } catch (Event e) { - if (content.str().size() > 0) { - try { - d = Data(escape(spaceNormalize(content.str())), Data::VERBATIM); - USER_DATA(ctx)->dataModel.init(data->id, d); - } catch (Event e) { - execContentRaise(ctx, e.name.c_str()); - } - } else { - execContentRaise(ctx, e.name.c_str()); - } - } - } - data++; - } - return USCXML_ERR_OK; - } - - static int execContentScript(const uscxml_ctx* ctx, const char* src, const char* content) { - if (content != NULL) { - USER_DATA(ctx)->dataModel.eval(Arabica::DOM::Element<std::string>(), content); - } else if (src != NULL) { - return USCXML_ERR_UNSUPPORTED; - } - return USCXML_ERR_OK; - } - - static void* dequeueExternal(const uscxml_ctx* ctx) { - tthread::lock_guard<tthread::mutex> lock(USER_DATA(ctx)->mutex); - if (USER_DATA(ctx)->eq.size() == 0) - return NULL; - - Event* e = USER_DATA(ctx)->eq.front(); - USER_DATA(ctx)->eq.pop_front(); - USER_DATA(ctx)->currEvent = e; - USER_DATA(ctx)->dataModel.setEvent(*e); - - std::map<std::string, StateMachine*>& allMachines = USER_DATA(ctx)->topMostMachine->allMachines; - if (e->invokeid.size() > 0 && allMachines.find(e->invokeid) != allMachines.end()) { - // we need to check for finalize content - StateMachine* invokedMachine = allMachines[e->invokeid]; - if (invokedMachine->invocation != NULL && invokedMachine->invocation->finalize != NULL) - invokedMachine->invocation->finalize(ctx, - invokedMachine->invocation, - e); - } - - // auto forward event - for (std::map<std::string, StateMachine*>::iterator machIter = allMachines.begin(); machIter != allMachines.end(); machIter++) { - if (machIter->second->parentMachine != NULL && - machIter->second->parentMachine == USER_DATA(ctx) && - machIter->second->invocation->autoforward) { - tthread::lock_guard<tthread::mutex> lock(machIter->second->mutex); - - Event* ne = new Event(*e); - machIter->second->eq.push_back(ne); - } - } - -#ifdef USCXML_VERBOSE - printf("Popping External Event: %s\n", e->name.c_str()); -#endif - return e; - } - - static void* dequeueInternal(const uscxml_ctx* ctx) { - if (USER_DATA(ctx)->iq.size() == 0) - return NULL; - Event* e = USER_DATA(ctx)->iq.front(); - USER_DATA(ctx)->iq.pop_front(); - USER_DATA(ctx)->currEvent = e; - USER_DATA(ctx)->dataModel.setEvent(*e); -#ifdef USCXML_VERBOSE - printf("Popping Internal Event: %s\n", e->name.c_str()); -#endif - return e; - } - - static void delayedSend(void* ctx, std::string eventName) { - tthread::lock_guard<tthread::mutex> lock(USER_DATA(ctx)->mutex); - - SendRequest* sr = USER_DATA(ctx)->sendIds[eventName]; - Event* e = new Event(*sr); - - if (sr->target == "#_internal") { - e->eventType = Event::INTERNAL; -#ifdef USCXML_VERBOSE - printf("Pushing Internal Event: %s\n", e->name.c_str()); -#endif - USER_DATA(ctx)->iq.push_back(e); - } else if (sr->target == "#_external") { - e->eventType = Event::EXTERNAL; -#ifdef USCXML_VERBOSE - printf("Pushing External Event: %s\n", e->name.c_str()); -#endif - USER_DATA(ctx)->eq.push_back(e); - } else if (sr->target == "#_parent") { - e->eventType = Event::EXTERNAL; - if (USER_DATA(ctx)->parentMachine != NULL) { - USER_DATA(ctx)->parentMachine->eq.push_back(e); - } - // TODO: handle invalid parent - } else if (sr->target.substr(0,8) == "#_scxml_") { - std::string sessionId = sr->target.substr(8); - bool sessionFound = false; - for (std::map<std::string, StateMachine*>::iterator machIter = USER_DATA(ctx)->topMostMachine->allMachines.begin(); - machIter != USER_DATA(ctx)->topMostMachine->allMachines.end(); machIter++) { - if (machIter->second->sessionId == sessionId) { - e->eventType = Event::EXTERNAL; - machIter->second->eq.push_back(e); - sessionFound = true; - break; - } - } - if (!sessionFound) { - // test496 - execContentRaise((uscxml_ctx*)ctx, "error.communication"); - } - } else if (sr->target.substr(0,2) == "#_") { - e->eventType = Event::EXTERNAL; - std::string targetId = sr->target.substr(2); - if (USER_DATA(ctx)->topMostMachine->allMachines.find(targetId) != USER_DATA(ctx)->topMostMachine->allMachines.end()) { - USER_DATA(ctx)->topMostMachine->allMachines[targetId]->eq.push_back(e); - } else { - execContentRaise((uscxml_ctx*)ctx, "error.communication"); - } - } else { - assert(false); - } - USER_DATA(ctx)->monitor.notify_all(); - delete sr; - } - - static std::string spaceNormalize(const std::string& text) { - std::stringstream content; - std::string seperator; - - size_t start = 0; - for (size_t i = 0; i < text.size(); i++) { - if (isspace(text[i])) { - if (i > 0 && start < i) { - content << seperator << text.substr(start, i - start); - seperator = " "; - } - while(isspace(text[++i])); // skip whitespaces - start = i; - } else if (i + 1 == text.size()) { - content << seperator << text.substr(start, i + 1 - start); - } - } - return content.str(); - } - - // TODO: isolate InterpreterImpl to reduce header deps on libxml/parser.h - static bool nameMatch(const std::string& eventDescs, const std::string& eventName) { - if(eventDescs.length() == 0 || eventName.length() == 0) - return false; - - // naive case of single descriptor and exact match - if (iequals(eventDescs, eventName)) - return true; - - size_t start = 0; - std::string eventDesc; - for (size_t i = 0; i < eventDescs.size(); i++) { - if (isspace(eventDescs[i])) { - if (i > 0 && start < i - 1) { - eventDesc = eventDescs.substr(start, i - start); - } - while(isspace(eventDescs[++i])); // skip whitespaces - start = i; - } else if (i + 1 == eventDescs.size()) { - eventDesc = eventDescs.substr(start, i + 1 - start); - } - - if (eventDesc.size() > 0) { - // remove optional trailing .* for CCXML compatibility - if (eventDesc.find("*", eventDesc.size() - 1) != std::string::npos) - eventDesc = eventDesc.substr(0, eventDesc.size() - 1); - if (eventDesc.find(".", eventDesc.size() - 1) != std::string::npos) - eventDesc = eventDesc.substr(0, eventDesc.size() - 1); - - // was eventDesc the * wildcard - if (eventDesc.size() == 0) - return true; - - // eventDesc has to be a real prefix of event now and therefore shorter - if (eventDesc.size() > eventName.size()) - goto NEXT_DESC; - - // are they already equal? - if (iequals(eventDesc, eventName)) - return true; - - if (eventName.find(eventDesc) == 0) { - if (eventName.find(".", eventDesc.size()) == eventDesc.size()) - return true; - } -NEXT_DESC: - eventDesc = ""; - } - } - return false; - } - - Event* currEvent; - - std::map<const uscxml_elem_invoke*, std::string> invocationIds; - std::map<std::string, StateMachine*> allMachines; - - bool isFinalized; - int state; - uscxml_ctx ctx; - const uscxml_machine* machine; - - StateMachine* parentMachine; - StateMachine* topMostMachine; - std::map<std::string, StateMachine* >::iterator currentMachine; // next machine to advance - - std::string baseURL; - std::string sessionId; - std::string name; - - // in case we were invoked - std::string invokeId; - const uscxml_elem_invoke* invocation; - std::map<std::string, Data> invokeData; - - std::deque<Event*> iq; - std::deque<Event*> eq; - - DataModel dataModel; - -protected: - struct scxml_foreach_info { - size_t iterations; - size_t currIteration; - }; - - NameSpaceInfo nsInfo; - std::map<std::string, IOProcessor> ioProcs; - std::map<std::string, Invoker> invokers; - Arabica::DOM::Document<std::string> document; - - DelayedEventQueue delayQueue; - std::map<std::string, SendRequest*> sendIds; - std::map<const uscxml_elem_foreach*, scxml_foreach_info*> foreachInfo; - - tthread::condition_variable monitor; - tthread::mutex mutex; -}; - - -int main(int argc, char** argv) { - - int err; - size_t benchmarkRuns = 1; - const char* envBenchmarkRuns = getenv("USCXML_BENCHMARK_ITERATIONS"); - if (envBenchmarkRuns != NULL) { - benchmarkRuns = strTo<size_t>(envBenchmarkRuns); - } - - size_t remainingRuns = benchmarkRuns; - - double avg = 0; - size_t microSteps = 0; -#ifdef BUILD_PROFILING - double avgDm = 0; -#endif - - StateMachine rootMachine(&USCXML_MACHINE); - - Timer tTotal; - tTotal.start(); - while(remainingRuns-- > 0) { - - Timer t; - t.start(); - microSteps = 0; - - - for (;;) { - err = rootMachine.step(); - if (rootMachine.isDone()) - break; - t.stop(); - microSteps++; - - t.start(); - } - microSteps++; - - assert(rootMachine.ctx.flags & USCXML_CTX_TOP_LEVEL_FINAL); - t.stop(); - - avg += t.elapsed; -#ifdef BUILD_PROFILING - avgDm += rootMachine.dataModel.timer.elapsed; - rootMachine.dataModel.timer.elapsed = 0; -#endif - size_t passIdx = 0; - for (size_t i = 0; i < rootMachine.ctx.machine->nr_states; i++) { - if (rootMachine.ctx.machine->states[i].name && strcmp(rootMachine.ctx.machine->states[i].name, "pass") == 0) { - passIdx = i; - break; - } - } - - if(!BIT_HAS(passIdx, rootMachine.ctx.config)) { - std::cerr << "Interpreter did not end in pass" << std::endl; - exit(EXIT_FAILURE); - } - rootMachine.reset(); - } - tTotal.stop(); - std::cout << benchmarkRuns << " iterations" << std::endl; - std::cout << tTotal.elapsed * 1000.0 << " ms in total" << std::endl; - std::cout << (avg * 1000.0) / (double)benchmarkRuns << " ms per execution" << std::endl; - std::cout << microSteps << " microsteps per iteration" << std::endl; - std::cout << (avg * 1000.0) / ((double)benchmarkRuns * (double)microSteps) << " ms per microstep" << std::endl; -#ifdef BUILD_PROFILING - std::cout << (avgDm * 1000.0) / (double)benchmarkRuns << " ms in dataModel" << std::endl; - std::cout << ((avg - avgDm) * 1000.0) / ((double)benchmarkRuns * (double)microSteps) << " ms per microstep \\wo dataModel" << std::endl; -#endif - tthread::this_thread::sleep_for(tthread::chrono::milliseconds(100)); - return EXIT_SUCCESS; -} |