summaryrefslogtreecommitdiffstats
path: root/src/uscxml/interpreter
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-01-08 21:59:18 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-01-08 21:59:18 (GMT)
commit030f3b483f54dbef6e164194a1771ef5b346312b (patch)
tree3f5b949b5ffed83d0b41a95d9fd3cfafd17cab2d /src/uscxml/interpreter
parent1ab8b9a0dcaa131b8cccc735a1794ce39b351715 (diff)
downloaduscxml-030f3b483f54dbef6e164194a1771ef5b346312b.zip
uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.tar.gz
uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.tar.bz2
Support for caching values on filesystem
Use USCXML_NOCACHE_FILES=YES to prevent, I will make this a build flag
Diffstat (limited to 'src/uscxml/interpreter')
-rw-r--r--src/uscxml/interpreter/BasicEventQueue.cpp18
-rw-r--r--src/uscxml/interpreter/FastMicroStep.cpp188
-rw-r--r--src/uscxml/interpreter/FastMicroStep.h33
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.cpp39
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.h7
-rw-r--r--src/uscxml/interpreter/MicroStepImpl.h3
6 files changed, 213 insertions, 75 deletions
diff --git a/src/uscxml/interpreter/BasicEventQueue.cpp b/src/uscxml/interpreter/BasicEventQueue.cpp
index 2f8bd48..519754e 100644
--- a/src/uscxml/interpreter/BasicEventQueue.cpp
+++ b/src/uscxml/interpreter/BasicEventQueue.cpp
@@ -35,17 +35,17 @@ Event BasicEventQueue::dequeue(size_t blockMs) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (blockMs > 0) {
- using namespace std::chrono;
+ using namespace std::chrono;
- // TODO: do read http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm
- system_clock::time_point now = system_clock::now();
- system_clock::time_point endTime = now + milliseconds(blockMs);
+ // TODO: do read http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm
+ system_clock::time_point now = system_clock::now();
+ system_clock::time_point endTime = now + milliseconds(blockMs);
+
+ // now + milliseconds(blockMs) may not have fitted into a duration type - limit to maximum duration
+ if (blockMs > system_clock::duration::max().count() - duration_cast<milliseconds>(now.time_since_epoch()).count()) {
+ endTime = system_clock::time_point::max();
+ }
- // now + milliseconds(blockMs) may not have fitted into a duration type - limit to maximum duration
- if (blockMs > system_clock::duration::max().count() - duration_cast<milliseconds>(now.time_since_epoch()).count()) {
- endTime = system_clock::time_point::max();
- }
-
// block for given milliseconds or until queue is non-empty
while (endTime > std::chrono::system_clock::now() && _queue.empty()) {
_cond.wait_until(_mutex, endTime);
diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp
index ed11fca..e41e9f7 100644
--- a/src/uscxml/interpreter/FastMicroStep.cpp
+++ b/src/uscxml/interpreter/FastMicroStep.cpp
@@ -22,6 +22,7 @@
#include "FastMicroStep.h"
#include "uscxml/util/DOM.h"
#include "uscxml/util/String.h"
+#include "uscxml/util/Base64.hpp"
#include "uscxml/util/Predicates.h"
#include "uscxml/util/Convenience.h"
#include "uscxml/interpreter/InterpreterMonitor.h"
@@ -102,6 +103,8 @@ void FastMicroStep::resortStates(DOMElement* element, const X& xmlPrefix) {
everything else
*/
+ // TODO: We can do this in one iteration
+
DOMElement* child = element->getFirstElementChild();
while(child) {
resortStates(child, xmlPrefix);
@@ -194,9 +197,11 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
_xmlPrefix = std::string(_xmlPrefix) + ":";
}
+ bool withCache = !envVarIsTrue("USCXML_NOCACHE_FILES");
+
resortStates(_scxml, _xmlPrefix);
-// assert(false);
-// throw NULL;
+
+ Data& cache = _callbacks->getCache().compound["FastMicroStep"];
/** -- All things states -- */
@@ -243,7 +248,20 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
_states[0]->data = DOMUtils::filterChildElements(_xmlPrefix.str() + "data", dataModels, false);
}
+ auto currState = cache.compound["states"].array.begin();
+ auto endState = cache.compound["states"].array.end();
+
for (i = 0; i < _states.size(); i++) {
+ Data* cachedState = NULL;
+ if (withCache) {
+ if (currState != endState) {
+ cachedState = &(*currState);
+ currState++;
+ } else {
+ cache.compound["states"].array.push_back(Data());
+ cachedState = &(*cache.compound["states"].array.rbegin());
+ }
+ }
// collect states with an id attribute
if (HAS_ATTR(_states[i]->element, "id")) {
_stateIds[ATTR(_states[i]->element, "id")] = i;
@@ -273,7 +291,6 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
}
}
-
// set the states type
if (false) {
} else if (iequals(TAGNAME(_states[i]->element), _xmlPrefix.str() + "initial")) {
@@ -297,17 +314,22 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
}
// establish the states' completion
- std::list<DOMElement*> completion = getCompletion(_states[i]->element);
- for (j = 0; j < _states.size(); j++) {
- if (!completion.empty() && _states[j]->element == completion.front()) {
- _states[i]->completion[j] = true;
- completion.pop_front();
- } else {
- _states[i]->completion[j] = false;
+ if (withCache && cachedState->compound.find("completion") != cachedState->compound.end()) {
+ _states[i]->completion = fromBase64(cachedState->compound["completion"]);
+ } else {
+ std::list<DOMElement*> completion = getCompletion(_states[i]->element);
+ for (j = 0; j < _states.size(); j++) {
+ if (!completion.empty() && _states[j]->element == completion.front()) {
+ _states[i]->completion[j] = true;
+ completion.pop_front();
+ } else {
+ _states[i]->completion[j] = false;
+ }
}
+ assert(completion.size() == 0);
+ if (withCache)
+ cachedState->compound["completion"] = Data(toBase64(_states[i]->completion));
}
- assert(completion.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;
@@ -354,46 +376,78 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
}
assert(tmp.size() == 0);
+ auto currTrans = cache.compound["transitions"].array.begin();
+ auto endTrans = cache.compound["transitions"].array.end();
+
for (i = 0; i < _transitions.size(); i++) {
+ Data* cachedTrans = NULL;
+ if (withCache) {
+ if (currTrans != endTrans) {
+ cachedTrans = &(*currTrans);
+ currTrans++;
+ } else {
+ cache.compound["transitions"].array.push_back(Data());
+ cachedTrans = &(*cache.compound["transitions"].array.rbegin());
+ }
+ }
// establish the transitions' exit set
assert(_transitions[i]->element != NULL);
-// std::cout << "i: " << i << std::endl << std::flush;
- std::list<DOMElement*> exitList = getExitSetCached(_transitions[i]->element, _scxml);
- _cache.exitSet[_transitions[i]->element] = exitList;
-
- for (j = 0; j < _states.size(); j++) {
- if (!exitList.empty() && _states[j]->element == exitList.front()) {
- _transitions[i]->exitSet[j] = true;
- exitList.pop_front();
- } else {
- _transitions[i]->exitSet[j] = false;
+
+ if (withCache && cachedTrans->compound.find("exitset") != cachedTrans->compound.end()) {
+ _transitions[i]->exitSet = fromBase64(cachedTrans->compound["exitset"]);
+ } else {
+ std::list<DOMElement*> exitList = getExitSetCached(_transitions[i]->element, _scxml);
+
+ for (j = 0; j < _states.size(); j++) {
+ if (!exitList.empty() && _states[j]->element == exitList.front()) {
+ _transitions[i]->exitSet[j] = true;
+ exitList.pop_front();
+ } else {
+ _transitions[i]->exitSet[j] = false;
+ }
}
+ assert(exitList.size() == 0);
+
+ if (withCache)
+ cachedTrans->compound["exitset"] = Data(toBase64(_transitions[i]->exitSet));
}
- assert(exitList.size() == 0);
// establish the transitions' conflict set
- for (j = i; j < _transitions.size(); j++) {
- if (conflictsCached(_transitions[i]->element, _transitions[j]->element, _scxml)) {
- _transitions[i]->conflicts[j] = true;
- } else {
- _transitions[i]->conflicts[j] = false;
+ if (withCache && cachedTrans->compound.find("conflicts") != cachedTrans->compound.end()) {
+ _transitions[i]->conflicts = fromBase64(cachedTrans->compound["conflicts"]);
+ } else {
+ for (j = i; j < _transitions.size(); j++) {
+ if (conflictsCached(_transitions[i]->element, _transitions[j]->element, _scxml)) {
+ _transitions[i]->conflicts[j] = true;
+ } else {
+ _transitions[i]->conflicts[j] = false;
+ }
+ // std::cout << ".";
}
-// std::cout << ".";
- }
- // conflicts matrix is symmetric
- for (j = 0; j < i; j++) {
- _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
- }
+ // conflicts matrix is symmetric
+ for (j = 0; j < i; j++) {
+ _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i];
+ }
+ if (withCache)
+ cachedTrans->compound["conflicts"] = Data(toBase64(_transitions[i]->conflicts));
+ }
// establish the transitions' target set
- std::list<std::string> targets = tokenize(ATTR(_transitions[i]->element, "target"));
- for (auto tIter = targets.begin(); tIter != targets.end(); tIter++) {
- if (_stateIds.find(*tIter) != _stateIds.end()) {
- _transitions[i]->target[_stateIds[*tIter]] = true;
+ if (withCache && cachedTrans->compound.find("target") != cachedTrans->compound.end()) {
+ _transitions[i]->target = fromBase64(cachedTrans->compound["target"]);
+ } else {
+ std::list<std::string> targets = tokenize(ATTR(_transitions[i]->element, "target"));
+ for (auto tIter = targets.begin(); tIter != targets.end(); tIter++) {
+ if (_stateIds.find(*tIter) != _stateIds.end()) {
+ _transitions[i]->target[_stateIds[*tIter]] = true;
+ }
}
+ if (withCache)
+ cachedTrans->compound["target"] = Data(toBase64(_transitions[i]->target));
+
}
// the transition's source
@@ -422,7 +476,6 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
_transitions[i]->type |= USCXML_TRANS_INITIAL;
}
-
// the transitions event and condition
_transitions[i]->event = (HAS_ATTR(_transitions[i]->element, "event") ?
ATTR(_transitions[i]->element, "event") : "");
@@ -433,10 +486,39 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) {
if (_transitions[i]->element->getChildElementCount() > 0) {
_transitions[i]->onTrans = _transitions[i]->element;
}
-
}
_cache.exitSet.clear();
_isInitialized = true;
+
+}
+
+std::string FastMicroStep::toBase64(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset) {
+ std::vector<boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type> bytes(bitset.num_blocks() + 1);
+ boost::to_block_range(bitset, bytes.begin());
+
+ std::string encoded;
+ encoded.resize(sizeof(boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type) * bytes.size());
+ bytes[bytes.size() - 1] = static_cast<boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type>(bitset.size());
+
+ static_assert(sizeof(boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type) >= sizeof(size_t), "Block type too small to encode dynamic_bitset length");
+
+ memcpy(&encoded[0], &bytes[0], sizeof(boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type) * bytes.size());
+ return base64Encode(encoded.c_str(), encoded.size(), true);
+}
+
+boost::dynamic_bitset<BITSET_BLOCKTYPE> FastMicroStep::fromBase64(const std::string& encoded) {
+
+ std::string decoded = base64Decode(encoded);
+ assert(decoded.size() % sizeof(boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type) == 0);
+ std::vector<boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type> bytes(decoded.size() / sizeof(boost::dynamic_bitset<BITSET_BLOCKTYPE>::block_type));
+
+ memcpy(&bytes[0], &decoded[0], decoded.size());
+
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> bitset;
+ bitset.init_from_block_range(bytes.begin(), --bytes.end());
+ bitset.resize(bytes[bytes.size() - 1]);
+
+ return bitset;
}
void FastMicroStep::markAsCancelled() {
@@ -451,13 +533,13 @@ InterpreterState FastMicroStep::step(size_t blockMs) {
size_t i, j, k;
- boost::dynamic_bitset<> exitSet(_states.size(), false);
- boost::dynamic_bitset<> entrySet(_states.size(), false);
- boost::dynamic_bitset<> targetSet(_states.size(), false);
- boost::dynamic_bitset<> tmpStates(_states.size(), false);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet(_states.size(), false);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> entrySet(_states.size(), false);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> targetSet(_states.size(), false);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> tmpStates(_states.size(), false);
- boost::dynamic_bitset<> conflicts(_transitions.size(), false);
- boost::dynamic_bitset<> transSet(_transitions.size(), false);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts(_transitions.size(), false);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> transSet(_transitions.size(), false);
#ifdef USCXML_VERBOSE
std::cerr << "Config: ";
@@ -675,14 +757,14 @@ ESTABLISH_ENTRYSET:
/* iterate for ancestors */
i = entrySet.find_first();
- while(i != boost::dynamic_bitset<>::npos) {
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
entrySet |= USCXML_GET_STATE(i).ancestors;
i = entrySet.find_next(i);
}
/* iterate for descendants */
i = entrySet.find_first();
- while(i != boost::dynamic_bitset<>::npos) {
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
switch (USCXML_STATE_MASK(USCXML_GET_STATE(i).type)) {
@@ -813,7 +895,7 @@ ESTABLISH_ENTRYSET:
/* TAKE_TRANSITIONS: */
i = transSet.find_first();
- while(i != boost::dynamic_bitset<>::npos) {
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
if ((USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) {
USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeTakingTransition, USCXML_GET_TRANS(i).element);
@@ -841,7 +923,7 @@ ESTABLISH_ENTRYSET:
/* ENTER_STATES: */
i = entrySet.find_first();
- while(i != boost::dynamic_bitset<>::npos) {
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
if (BIT_HAS(i, _configuration)) {
// already active
@@ -924,7 +1006,7 @@ ESTABLISH_ENTRYSET:
BIT_HAS(j, USCXML_GET_STATE(i).ancestors)) {
tmpStates.reset();
k = _configuration.find_first();
- while (k != boost::dynamic_bitset<>::npos) {
+ while (k != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
if (BIT_HAS(j, USCXML_GET_STATE(k).ancestors)) {
if (USCXML_STATE_MASK(USCXML_GET_STATE(k).type) == USCXML_STATE_FINAL) {
tmpStates ^= USCXML_GET_STATE(k).ancestors;
@@ -981,7 +1063,7 @@ bool FastMicroStep::isInState(const std::string& stateId) {
std::list<XERCESC_NS::DOMElement*> FastMicroStep::getConfiguration() {
std::list<XERCESC_NS::DOMElement*> config;
size_t i = _configuration.find_first();
- while(i != boost::dynamic_bitset<>::npos) {
+ while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) {
config.push_back(_states[i]->element);
i = _configuration.find_next(i);
}
@@ -1038,7 +1120,7 @@ std::list<DOMElement*> FastMicroStep::getHistoryCompletion(const DOMElement* his
/**
* Print name of states contained in a (debugging).
*/
-void FastMicroStep::printStateNames(const boost::dynamic_bitset<>& a) {
+void FastMicroStep::printStateNames(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& a) {
size_t i;
const char* seperator = "";
for (i = 0; i < a.size(); i++) {
diff --git a/src/uscxml/interpreter/FastMicroStep.h b/src/uscxml/interpreter/FastMicroStep.h
index 810b793..db3e724 100644
--- a/src/uscxml/interpreter/FastMicroStep.h
+++ b/src/uscxml/interpreter/FastMicroStep.h
@@ -33,6 +33,12 @@
#include <boost/dynamic_bitset.hpp>
+#ifdef _WIN32
+#define BITSET_BLOCKTYPE size_t
+#else
+#define BITSET_BLOCKTYPE
+#endif
+
namespace uscxml {
/**
@@ -57,11 +63,11 @@ protected:
Transition() : element(NULL), source(0), onTrans(NULL), type(0) {}
XERCESC_NS::DOMElement* element;
- boost::dynamic_bitset<> conflicts;
- boost::dynamic_bitset<> exitSet;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet;
uint32_t source;
- boost::dynamic_bitset<> target;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> target;
XERCESC_NS::DOMElement* onTrans;
@@ -77,9 +83,9 @@ protected:
State() : element(NULL), parent(0), documentOrder(0), doneData(NULL), type(0) {}
XERCESC_NS::DOMElement* element;
- boost::dynamic_bitset<> completion;
- boost::dynamic_bitset<> children;
- boost::dynamic_bitset<> ancestors;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> completion;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> children;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> ancestors;
uint32_t parent;
uint32_t documentOrder;
@@ -108,12 +114,12 @@ protected:
std::vector<Transition*> _transitions;
std::list<XERCESC_NS::DOMElement*> _globalScripts;
- boost::dynamic_bitset<> _configuration;
- boost::dynamic_bitset<> _invocations;
- boost::dynamic_bitset<> _history;
- boost::dynamic_bitset<> _initializedData;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> _configuration;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> _invocations;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> _history;
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> _initializedData;
- std::set<boost::dynamic_bitset<> > _microstepConfigurations;
+ std::set<boost::dynamic_bitset<BITSET_BLOCKTYPE> > _microstepConfigurations;
Binding _binding;
XERCESC_NS::DOMElement* _scxml;
@@ -130,13 +136,16 @@ private:
bool conflictsCached(const XERCESC_NS::DOMElement* t1, const XERCESC_NS::DOMElement* t2, const XERCESC_NS::DOMElement* root); ///< overrides implementation Predicates::conflicts for speed
+ std::string toBase64(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset);
+ boost::dynamic_bitset<BITSET_BLOCKTYPE> fromBase64(const std::string& encoded);
+
std::list<XERCESC_NS::DOMElement*> getExitSetCached(const XERCESC_NS::DOMElement* transition,
const XERCESC_NS::DOMElement* root);
CachedPredicates _cache;
#ifdef USCXML_VERBOSE
- void printStateNames(const boost::dynamic_bitset<>& bitset);
+ void printStateNames(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset);
#endif
};
diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp
index 43059bf..8762b95 100644
--- a/src/uscxml/interpreter/InterpreterImpl.cpp
+++ b/src/uscxml/interpreter/InterpreterImpl.cpp
@@ -27,11 +27,13 @@
#include "uscxml/messages/Event.h"
#include "uscxml/util/String.h"
#include "uscxml/util/Predicates.h"
+#include "uscxml/util/MD5.hpp"
#include "uscxml/plugins/InvokerImpl.h"
#include "uscxml/interpreter/Logging.h"
#include <iostream>
+#include <fstream>
#include <assert.h>
#include <algorithm>
@@ -108,6 +110,15 @@ InterpreterImpl::~InterpreterImpl() {
// assert(_invokers.size() == 0);
// ::xercesc_3_1::XMLPlatformUtils::Terminate();
+ if (!envVarIsTrue("USCXML_NOCACHE_FILES")) {
+ // save our cache
+ std::string sharedTemp = URL::getTempDir(true);
+ std::ofstream dataFS(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache");
+ if (dataFS) {
+ dataFS << _cache;
+ dataFS.close();
+ }
+ }
}
void InterpreterImpl::cancel() {
@@ -159,7 +170,6 @@ SCXML_STOP_SEARCH:
_binding = (HAS_ATTR(_scxml, "binding") && iequals(ATTR(_scxml, "binding"), "late") ? LATE : EARLY);
}
-
}
void InterpreterImpl::init() {
@@ -169,6 +179,33 @@ void InterpreterImpl::init() {
setupDOM();
+ if (!envVarIsTrue("USCXML_NOCACHE_FILES")) {
+ // try to open chached data from resource directory
+ std::string sharedTemp = URL::getTempDir(true);
+ std::ifstream dataFS(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache");
+ if (dataFS.is_open()) {
+ std::string cacheStr((std::istreambuf_iterator<char>(dataFS)),
+ std::istreambuf_iterator<char>());
+ _cache = Data::fromJSON(cacheStr);
+ }
+
+ // get md5 of current document
+ std::stringstream ss;
+ ss << *_document;
+ _md5 = md5(ss.str());
+
+ if (_cache.compound.find("InterpreterImpl") != _cache.compound.end() &&
+ _cache.compound["InterpreterImpl"].compound.find("md5") != _cache.compound["InterpreterImpl"].compound.end() &&
+ _cache.compound["InterpreterImpl"].compound["md5"].atom != _md5) {
+
+ // that's not our cache!
+ _cache.clear();
+ }
+
+ _cache.compound["InterpreterImpl"].compound["baseURL"] = Data(std::string(_baseURL));
+ _cache.compound["InterpreterImpl"].compound["md5"] = Data(_md5);
+ }
+
// register io processors
std::map<std::string, IOProcessorImpl*> ioProcs = _factory->getIOProcessors();
for (auto ioProcIter = ioProcs.begin(); ioProcIter != ioProcs.end(); ioProcIter++) {
diff --git a/src/uscxml/interpreter/InterpreterImpl.h b/src/uscxml/interpreter/InterpreterImpl.h
index 1243f7c..0efc70a 100644
--- a/src/uscxml/interpreter/InterpreterImpl.h
+++ b/src/uscxml/interpreter/InterpreterImpl.h
@@ -143,6 +143,10 @@ public:
return Interpreter(shared_from_this());
}
+ virtual Data& getCache() {
+ return _cache;
+ }
+
/**
DataModelCallbacks
*/
@@ -284,6 +288,7 @@ protected:
Factory* _factory;
URL _baseURL;
+ std::string _md5;
MicroStep _microStepper;
DataModel _dataModel;
@@ -305,6 +310,8 @@ protected:
std::set<std::string> _autoForwarders;
std::set<InterpreterMonitor*> _monitors;
+ Data _cache;
+
private:
void setupDOM();
};
diff --git a/src/uscxml/interpreter/MicroStepImpl.h b/src/uscxml/interpreter/MicroStepImpl.h
index 1544e78..e3f8299 100644
--- a/src/uscxml/interpreter/MicroStepImpl.h
+++ b/src/uscxml/interpreter/MicroStepImpl.h
@@ -60,6 +60,9 @@ public:
virtual std::set<InterpreterMonitor*> getMonitors() = 0;
virtual Interpreter getInterpreter() = 0;
virtual Logger getLogger() = 0;
+
+ /** Saved State */
+ virtual Data& getCache() = 0;
};
/**