summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-07-13 20:29:09 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-07-13 20:29:09 (GMT)
commit04b04aa6624caf73ffe4fc33f918e7f48b27da37 (patch)
tree40a8f92a0abd081f59a8aacc4b726dabf3c8f2f5
parente0d6ac8097bfd148a9956128a48b7d1addf81e68 (diff)
downloaduscxml-04b04aa6624caf73ffe4fc33f918e7f48b27da37.zip
uscxml-04b04aa6624caf73ffe4fc33f918e7f48b27da37.tar.gz
uscxml-04b04aa6624caf73ffe4fc33f918e7f48b27da37.tar.bz2
LambdaMonitors and prepared use-case examples
-rw-r--r--CMakeLists.txt4
-rw-r--r--README.md40
-rw-r--r--contrib/cmake/CPackUSCXML.cmake5
-rw-r--r--contrib/cmake/FindUSCXML.cmake84
-rw-r--r--docs/BENCHMARKS.md26
-rw-r--r--examples/cpp/library/lambdas/CMakeLists.txt10
-rw-r--r--examples/cpp/library/lambdas/main.cpp17
-rw-r--r--examples/cpp/library/simple/CMakeLists.txt10
-rw-r--r--examples/cpp/library/simple/main.cpp17
-rw-r--r--examples/cpp/transpiled/arduino/WaterPump.cxx (renamed from apps/arduino/WaterPump.cxx)0
-rw-r--r--examples/cpp/transpiled/arduino/WaterPump.scxml (renamed from apps/arduino/WaterPump.scxml)0
-rw-r--r--examples/cpp/transpiled/arduino/stateMachine.c (renamed from apps/arduino/stateMachine.c)0
-rw-r--r--src/apps/uscxml-browser.cpp (renamed from apps/uscxml-browser.cpp)0
-rw-r--r--src/apps/uscxml-browser.vbs (renamed from apps/uscxml-browser.vbs)0
-rw-r--r--src/apps/uscxml-debugger.html (renamed from apps/uscxml-debugger.html)0
-rw-r--r--src/apps/uscxml-transform.cpp (renamed from apps/uscxml-transform.cpp)0
-rw-r--r--src/uscxml/Interpreter.cpp4
-rw-r--r--src/uscxml/Interpreter.h5
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.cpp13
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.h6
-rw-r--r--src/uscxml/interpreter/InterpreterMonitor.h321
-rw-r--r--src/uscxml/util/Predicates.cpp1
-rw-r--r--test/src/test-snippets.cpp25
23 files changed, 533 insertions, 55 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8a4ff9e..4c2e3dd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -527,13 +527,13 @@ if (NOT CMAKE_CROSSCOMPILING)
add_subdirectory(test)
endif()
-add_executable(uscxml-browser apps/uscxml-browser.cpp ${GETOPT_FILES})
+add_executable(uscxml-browser src/apps/uscxml-browser.cpp ${GETOPT_FILES})
set_property(TARGET uscxml-browser PROPERTY CXX_STANDARD 11)
set_property(TARGET uscxml-browser PROPERTY CXX_STANDARD_REQUIRED ON)
install_executable(TARGETS uscxml-browser COMPONENT tools)
target_link_libraries(uscxml-browser uscxml)
-add_executable(uscxml-transform apps/uscxml-transform.cpp ${GETOPT_FILES})
+add_executable(uscxml-transform src/apps/uscxml-transform.cpp ${GETOPT_FILES})
set_property(TARGET uscxml-transform PROPERTY CXX_STANDARD 11)
set_property(TARGET uscxml-transform PROPERTY CXX_STANDARD_REQUIRED ON)
install_executable(TARGETS uscxml-transform COMPONENT tools)
diff --git a/README.md b/README.md
index 7ba0406..c1f7ea7 100644
--- a/README.md
+++ b/README.md
@@ -8,11 +8,11 @@
- [Changes](docs/CHANGES.md)
- [Tests passed](test/w3c/TESTS.md)
- [Publications](docs/PUBLICATIONS.md)
+- [Benchmarks](docs/BENCHMARKS.md)
## What is it?
-uSCXML is a platform to work with state-charts given as
-[SCXML](http://www.w3.org/TR/scxml/) files. It consists of three principal components:
+uSCXML is a platform to work with state-charts given as [SCXML](http://www.w3.org/TR/scxml/) files. It features the [fastest microstep](docs/BENCHMARKS.md) implementation available and consists of three principal components:
1. `libuscxml`: [C++ library](#embedded-as-a-library) containing an interpreter and accompanying functionality.
@@ -20,9 +20,7 @@ uSCXML is a platform to work with state-charts given as
3. `uscxml-transform`: A collection of [transformation](#for-transformations) implementations to transpile SCXML, e.g. onto ANSI-C and VHDL.
-The status of the various datamodels, bindings and generators with regard to the [W3C IRP
-tests](https://www.w3.org/Voice/2013/scxml-irp/) can be checked in the [test
-table](test/w3c/TESTS.md).
+The status of the various datamodels, bindings and generators with regard to the [W3C IRPtests](https://www.w3.org/Voice/2013/scxml-irp/) can be checked in the [test table](test/w3c/TESTS.md).
## Installation
@@ -58,15 +56,13 @@ For more detailled information, refer to the [documentation](http://tklab-tud.gi
**Examples:**
-* [uscxml-browser.cpp](https://github.com/tklab-tud/uscxml/blob/master/apps/uscxml-browser.cpp) (**C++**)
+* [uscxml-browser.cpp](https://github.com/tklab-tud/uscxml/blob/master/src/apps/uscxml-browser.cpp) (**C++**)
* [test-state-pass.cpp](https://github.com/tklab-tud/uscxml/blob/master/test/src/test-state-pass.cpp) (**C++**)
* [TestStatePass.cs](https://github.com/tklab-tud/uscxml/blob/master/contrib/csharp/bindings/TestStatePass.cs) (**C#**)
* [test-state-pass.py](https://github.com/tklab-tud/uscxml/blob/master/contrib/python/bindings/test-state-pass.py) (**Python**)
* [JexlDataModelTest.java](https://github.com/tklab-tud/uscxml/blob/master/contrib/java/bindings/org/uscxml/tests/JexlDataModelTest.java) (**Java**)
-
-
### On the Command-line
# interpret state-chart from url
$ uscxml-browser https://raw.githubusercontent.com/tklab-tud/uscxml/master/test/w3c/null/test436.scxml
@@ -78,34 +74,8 @@ For more detailled information, refer to the [documentation](http://tklab-tud.gi
**Examples:**
* [test-gen-c.cpp](https://github.com/tklab-tud/uscxml/blob/master/test/src/test-gen-c.cpp) (**C++**)
-* [WaterPump.cxx](https://github.com/tklab-tud/uscxml/blob/master/apps/arduino/WaterPump.cxx) (**C++ on Arduino**)
-
-## Benchmarks
-
-We did conceive a [series of benchmark](https://github.com/tklab-tud/uscxml/tree/master/test/benchmarks) SCXML documents to evaluate the performance of the various SCXML implementations. The state-charts in the benchmarks are completely artificial and bear no resemblance to real-world state-charts. However, they may provide a general guidance to get an impression about the performance of the different implementations.
-
-The state-charts each stress a specific feature of any SCXML `microstep(T)` implementation. Each contains a state `mark` that is continuously entered and exited as part of a sequence of spontaneous microsteps and measures the entries per second. For every implementation, the [benchmark is run](https://github.com/tklab-tud/uscxml/blob/master/contrib/benchmarks/run.sh) for a number of seconds and the iterations per seconds are averaged. The benchmarks exist in increasing complexity from very simple with, e.g., 4 states nested in a depth of 4 compounds up until 512 for state-charts with > 250.000 states.
-
-**Note:** If you are the author / maintainer of one of the SCXML implementations being benchmarked below and feel that I misrepresent your implementation's performance, post an issue and I will set things straight.
-
-**Note:** There are two `microstep(T)` implementations in uSCXML, namely `fast` and `large` with the former being the default for transpilation and the latter for interpretation. Both are being employed on an interpreted state-chart here. For the `fast` microstep implementation we measured the case with pre-calculated predicates.
-
-**Note:** The numbers for scxmlcc are necessarily for the compiled case and N/A if we could not compile the state-chart within the time limit.
-
-### Transitions
-
-The Transitions benchmark measures transition selection with many conflicting transitions enabled as part of a microstep.
-
-![Transition Benchmark](https://user-images.githubusercontent.com/980655/27858834-004c9c78-6177-11e7-8519-2f73f0ff9fb4.png)
-
-### LCCA
-When exiting a state via a transition, the least-common compound ancestor (LCCA) of the transition's targets and source state has to be identified. This is a common operation and its runtime is proportional to the nesting depth if implemented respectively.
-
-![LCCA Benchmark](https://user-images.githubusercontent.com/980655/27858835-00527ecc-6177-11e7-85d2-46c83ad5ed71.png)
-
-### Conclusion
+* [WaterPump.cxx](https://github.com/tklab-tud/uscxml/blob/master/src/apps/arduino/WaterPump.cxx) (**C++ on Arduino**)
-uSCXML with either microstep implementation is consistently the fastest with the exception of the Transitions benchmark, where the compiled `scxmlcc` is degenerating slower for more complex state-charts. This may be due to compiler optimizations (or an incomplete implementation) and it would be interesting to compare `scxmlcc` against the transpiled ANSI-C code from `uscxml-transform`. However, the limiting factor here becomes the time required to transpile the state-chart or to compile the generated source file into an executable binary respectively. With regard to huge state-charts, the large microstep implementation of `uSCXML` performs best and retains acceptable performance throughout the range of benchmarks, only surpassed by the fast implementation for smaller complexities.
## Changes
diff --git a/contrib/cmake/CPackUSCXML.cmake b/contrib/cmake/CPackUSCXML.cmake
index 2a6f88b..e9bc5ec 100644
--- a/contrib/cmake/CPackUSCXML.cmake
+++ b/contrib/cmake/CPackUSCXML.cmake
@@ -146,6 +146,11 @@ set(CPACK_DEBIAN_PACKAGE_NAME "uscxml")
set(CPACK_RPM_PACKAGE_NAME "uscxml")
set(CPACK_RPM_PACKAGE_LICENSE "Simplified BSD")
+########################################
+# CMake Modules for clients
+########################################
+
+install(FILES ${PROJECT_SOURCE_DIR}/contrib/cmake/FindUSCXML.cmake DESTINATION share/uscxml/cmake COMPONENT library)
########################################
# Describe layout of package
diff --git a/contrib/cmake/FindUSCXML.cmake b/contrib/cmake/FindUSCXML.cmake
new file mode 100644
index 0000000..bf3605d
--- /dev/null
+++ b/contrib/cmake/FindUSCXML.cmake
@@ -0,0 +1,84 @@
+# - Find USCXML
+# This module checks if uSCXML is installed and determines where the
+# include files and libraries are. This code sets the following
+# variables:
+#
+# USCXML_INCLUDE_DIR = The full path to the uscxml headers
+# USCXML_LIBRARIES = All uscxml libraries for release and debug builds
+#
+# Example:
+# find_package(USCXML REQUIRED)
+# include_directories(${USCXML_INCLUDE_DIR})
+#
+
+###################################################
+# where to search for uscxml headers and libraries
+###################################################
+set(_USCXML_LIB_SEARCHPATH
+ ${USCXML_LIBRARY_ROOT}
+ "/usr/local"
+ "/opt/local"
+ "C:/Program Files (x86)/uSCXML"
+ "C:/Program Files/uSCXML"
+)
+
+###################################################
+# find the uSCXML header files
+###################################################
+FIND_PATH(USCXML_INCLUDE_DIR uscxml/uscxml.h
+ PATH_SUFFIXES include
+ PATHS ${_USCXML_LIB_SEARCHPATH} ${USCXML_HEADER_ROOT}
+ ENV USCXML_INCLUDE_DIR
+)
+
+
+set(USCXML_LIBRARIES)
+# prefer MinSizeRel libraries
+FIND_LIBRARY(USCXML_LIBRARY_RELEASE
+ PATH_SUFFIXES lib
+ NAMES uscxml_s
+ PATHS ${_USCXML_LIB_SEARCHPATH}
+ ENV USCXML_LIB_DIR
+)
+if (USCXML_LIBRARY_RELEASE)
+ list(APPEND USCXML_LIBRARIES optimized ${USCXML_LIBRARY_RELEASE})
+else()
+ # if no minsize libraries were found try normal release
+ FIND_LIBRARY(USCXML_LIBRARY_RELEASE
+ PATH_SUFFIXES lib
+ NAMES uscxml
+ PATHS ${_USCXML_LIB_SEARCHPATH}
+ ENV USCXML_LIB_DIR
+ )
+ if (USCXML_LIBRARY_RELEASE)
+ list(APPEND USCXML_LIBRARIES optimized USCXML_LIBRARY_RELEASE)
+ endif()
+endif()
+
+# prefer release with debug libraries
+FIND_LIBRARY(USCXML_LIBRARY_DEBUG
+ PATH_SUFFIXES lib
+ NAMES uscxml_rd
+ PATHS ${_USCXML_LIB_SEARCHPATH}
+ ENV USCXML_LIB_DIR
+)
+if ("${USCXML_LIBRARY_DEBUG}")
+ list(APPEND USCXML_LIBRARIES debug ${USCXML_LIBRARY_DEBUG})
+else()
+ # go for normal debug libraries insteaf
+ FIND_LIBRARY(USCXML_LIBRARY_DEBUG
+ PATH_SUFFIXES lib
+ NAMES uscxml_d
+ PATHS ${_USCXML_LIB_SEARCHPATH}
+ ENV USCXML_LIB_DIR
+ )
+ if ("${USCXML_LIBRARY_DEBUG}")
+ list(APPEND USCXML_LIBRARIES debug USCXML_LIBRARY_DEBUG)
+ endif()
+endif()
+
+
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(USCXML DEFAULT_MSG USCXML_LIBRARIES USCXML_INCLUDE_DIR)
+MARK_AS_ADVANCED(USCXML_INCLUDE_DIR USCXML_LIBRARIES)
diff --git a/docs/BENCHMARKS.md b/docs/BENCHMARKS.md
new file mode 100644
index 0000000..685c287
--- /dev/null
+++ b/docs/BENCHMARKS.md
@@ -0,0 +1,26 @@
+# Benchmarks
+
+We did conceive a [series of benchmark](https://github.com/tklab-tud/uscxml/tree/master/test/benchmarks) SCXML documents to evaluate the performance of the various SCXML implementations. The state-charts in the benchmarks are completely artificial and bear no resemblance to real-world state-charts. However, they may provide a general guidance to get an impression about the performance of the different implementations.
+
+The state-charts each stress a specific feature of any SCXML `microstep(T)` implementation. Each contains a state `mark` that is continuously entered and exited as part of a sequence of spontaneous microsteps and measures the entries per second. For every implementation, the [benchmark is run](https://github.com/tklab-tud/uscxml/blob/master/contrib/benchmarks/run.sh) for a number of seconds and the iterations per seconds are averaged. The benchmarks exist in increasing complexity from very simple with, e.g., 4 states nested in a depth of 4 compounds up until 512 for state-charts with > 250.000 states.
+
+**Note:** If you are the author / maintainer of one of the SCXML implementations being benchmarked below and feel that I misrepresent your implementation's performance, post an issue and I will set things straight.
+
+**Note:** There are two `microstep(T)` implementations in uSCXML, namely `fast` and `large` with the former being the default for transpilation and the latter for interpretation. Both are being employed on an interpreted state-chart here. For the `fast` microstep implementation we measured the case with pre-calculated predicates.
+
+**Note:** The numbers for scxmlcc are necessarily for the compiled case and N/A if we could not compile the state-chart within the time limit.
+
+## Transitions
+
+The Transitions benchmark measures transition selection with many conflicting transitions enabled as part of a microstep.
+
+![Transition Benchmark](https://user-images.githubusercontent.com/980655/27858834-004c9c78-6177-11e7-8519-2f73f0ff9fb4.png)
+
+## LCCA
+When exiting a state via a transition, the least-common compound ancestor (LCCA) of the transition's targets and source state has to be identified. This is a common operation and its runtime is proportional to the nesting depth if implemented respectively.
+
+![LCCA Benchmark](https://user-images.githubusercontent.com/980655/27858835-00527ecc-6177-11e7-85d2-46c83ad5ed71.png)
+
+## Conclusion
+
+uSCXML with either microstep implementation is consistently the fastest with the exception of the Transitions benchmark, where the compiled `scxmlcc` is degenerating slower for more complex state-charts. This may be due to compiler optimizations (or an incomplete implementation) and it would be interesting to compare `scxmlcc` against the transpiled ANSI-C code from `uscxml-transform`. However, the limiting factor here becomes the time required to transpile the state-chart or to compile the generated source file into an executable binary respectively. With regard to huge state-charts, the large microstep implementation of `uSCXML` performs best and retains acceptable performance throughout the range of benchmarks, only surpassed by the fast implementation for smaller complexities.
diff --git a/examples/cpp/library/lambdas/CMakeLists.txt b/examples/cpp/library/lambdas/CMakeLists.txt
new file mode 100644
index 0000000..c062e64
--- /dev/null
+++ b/examples/cpp/library/lambdas/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.6)
+project(simple-scxml)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/usr/local/share/uscxml/cmake/")
+find_package(USCXML REQUIRED)
+
+
+include_directories(${USCXML_INCLUDE_DIR})
+add_executable(simple main.cpp)
+target_link_libraries(simple ${USCXML_LIBRARIES}) \ No newline at end of file
diff --git a/examples/cpp/library/lambdas/main.cpp b/examples/cpp/library/lambdas/main.cpp
new file mode 100644
index 0000000..316576b
--- /dev/null
+++ b/examples/cpp/library/lambdas/main.cpp
@@ -0,0 +1,17 @@
+#include <iostream>
+#include "uscxml/uscxml.h"
+
+int main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ std::cerr << "Expected URL with SCXML document as first argument" << std::endl;
+ return -1;
+ }
+
+ uscxml::Interpreter sc = uscxml::Interpreter::fromURL(argv[1]);
+ uscxml::InterpreterState state;
+ while ((state = sc.step()) != uscxml::USCXML_FINISHED) {
+ }
+
+ return 0;
+}
diff --git a/examples/cpp/library/simple/CMakeLists.txt b/examples/cpp/library/simple/CMakeLists.txt
new file mode 100644
index 0000000..c062e64
--- /dev/null
+++ b/examples/cpp/library/simple/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.6)
+project(simple-scxml)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/usr/local/share/uscxml/cmake/")
+find_package(USCXML REQUIRED)
+
+
+include_directories(${USCXML_INCLUDE_DIR})
+add_executable(simple main.cpp)
+target_link_libraries(simple ${USCXML_LIBRARIES}) \ No newline at end of file
diff --git a/examples/cpp/library/simple/main.cpp b/examples/cpp/library/simple/main.cpp
new file mode 100644
index 0000000..316576b
--- /dev/null
+++ b/examples/cpp/library/simple/main.cpp
@@ -0,0 +1,17 @@
+#include <iostream>
+#include "uscxml/uscxml.h"
+
+int main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ std::cerr << "Expected URL with SCXML document as first argument" << std::endl;
+ return -1;
+ }
+
+ uscxml::Interpreter sc = uscxml::Interpreter::fromURL(argv[1]);
+ uscxml::InterpreterState state;
+ while ((state = sc.step()) != uscxml::USCXML_FINISHED) {
+ }
+
+ return 0;
+}
diff --git a/apps/arduino/WaterPump.cxx b/examples/cpp/transpiled/arduino/WaterPump.cxx
index 01f4cfa..01f4cfa 100644
--- a/apps/arduino/WaterPump.cxx
+++ b/examples/cpp/transpiled/arduino/WaterPump.cxx
diff --git a/apps/arduino/WaterPump.scxml b/examples/cpp/transpiled/arduino/WaterPump.scxml
index a7d8bad..a7d8bad 100644
--- a/apps/arduino/WaterPump.scxml
+++ b/examples/cpp/transpiled/arduino/WaterPump.scxml
diff --git a/apps/arduino/stateMachine.c b/examples/cpp/transpiled/arduino/stateMachine.c
index a74535b..a74535b 100644
--- a/apps/arduino/stateMachine.c
+++ b/examples/cpp/transpiled/arduino/stateMachine.c
diff --git a/apps/uscxml-browser.cpp b/src/apps/uscxml-browser.cpp
index dd0633b..dd0633b 100644
--- a/apps/uscxml-browser.cpp
+++ b/src/apps/uscxml-browser.cpp
diff --git a/apps/uscxml-browser.vbs b/src/apps/uscxml-browser.vbs
index fc8ea9a..fc8ea9a 100644
--- a/apps/uscxml-browser.vbs
+++ b/src/apps/uscxml-browser.vbs
diff --git a/apps/uscxml-debugger.html b/src/apps/uscxml-debugger.html
index fa49554..fa49554 100644
--- a/apps/uscxml-debugger.html
+++ b/src/apps/uscxml-debugger.html
diff --git a/apps/uscxml-transform.cpp b/src/apps/uscxml-transform.cpp
index e99ed68..e99ed68 100644
--- a/apps/uscxml-transform.cpp
+++ b/src/apps/uscxml-transform.cpp
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index c4025ba..f3aedee 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -271,6 +271,10 @@ std::list<InterpreterIssue> Interpreter::validate() {
return InterpreterIssue::forInterpreter(_impl.get());
}
+LambdaMonitor& Interpreter::on() {
+ return _impl->on();
+}
+
#if 1
static void printNodeSet(Logger& logger, const std::list<XERCESC_NS::DOMElement*> nodes) {
std::string seperator;
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 3c44400..aff77a2 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -34,6 +34,7 @@
#include "uscxml/interpreter/ContentExecutor.h"
#include "uscxml/interpreter/EventQueue.h"
#include "uscxml/interpreter/InterpreterState.h"
+#include "uscxml/interpreter/InterpreterMonitor.h"
#ifdef max
#error define NOMINMAX or undefine the max macro please (https://support.microsoft.com/en-us/kb/143208)
@@ -42,6 +43,7 @@
namespace uscxml {
class InterpreterMonitor;
+class LambdaMonitor;
class InterpreterImpl;
class InterpreterIssue;
@@ -234,6 +236,9 @@ public:
std::shared_ptr<InterpreterImpl> getImpl() const {
return _impl;
}
+
+ LambdaMonitor& on();
+
#if 0
// "Ambiguous user-defined-conversion" with operator bool() on MSVC from Visual Studio 12
explicit operator MicroStepCallbacks*() {
diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp
index 414dba2..1caa3f0 100644
--- a/src/uscxml/interpreter/InterpreterImpl.cpp
+++ b/src/uscxml/interpreter/InterpreterImpl.cpp
@@ -103,6 +103,9 @@ InterpreterImpl::~InterpreterImpl() {
if (_document)
delete _document;
+ if (_lambdaMonitor)
+ delete _lambdaMonitor;
+
{
std::lock_guard<std::recursive_mutex> lock(_instanceMutex);
_instances.erase(getSessionId());
@@ -139,7 +142,7 @@ void InterpreterImpl::reset() {
if (_microStepper)
_microStepper.reset();
- _isInitialized = false;
+// _isInitialized = false;
_state = USCXML_INSTANTIATED;
// _dataModel.reset();
if (_delayQueue)
@@ -622,4 +625,12 @@ void InterpreterImpl::enqueueAtParent(const Event& event) {
}
+LambdaMonitor& InterpreterImpl::on() {
+ if (_lambdaMonitor == NULL) {
+ _lambdaMonitor = new LambdaMonitor();
+ addMonitor(_lambdaMonitor);
+ }
+ return *_lambdaMonitor;
+}
+
}
diff --git a/src/uscxml/interpreter/InterpreterImpl.h b/src/uscxml/interpreter/InterpreterImpl.h
index 42d61f2..2f5fb07 100644
--- a/src/uscxml/interpreter/InterpreterImpl.h
+++ b/src/uscxml/interpreter/InterpreterImpl.h
@@ -269,9 +269,13 @@ public:
return _document;
}
+ LambdaMonitor& on();
+
protected:
static void addInstance(std::shared_ptr<InterpreterImpl> instance);
-
+
+ LambdaMonitor* _lambdaMonitor = NULL;
+
Binding _binding;
ActionLanguage _al;
diff --git a/src/uscxml/interpreter/InterpreterMonitor.h b/src/uscxml/interpreter/InterpreterMonitor.h
index 43b7f53..ed62675 100644
--- a/src/uscxml/interpreter/InterpreterMonitor.h
+++ b/src/uscxml/interpreter/InterpreterMonitor.h
@@ -65,26 +65,47 @@ public:
InterpreterMonitor(Logger logger) : _copyToInvokers(false), _logger(logger) {}
virtual ~InterpreterMonitor() {}
- virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event) {}
+ 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 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 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 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 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 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 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) {}
@@ -92,7 +113,8 @@ public:
virtual void beforeCompletion(const std::string& sessionId) {}
virtual void afterCompletion(const std::string& sessionId) {}
- virtual void reportIssue(const std::string& sessionId, const InterpreterIssue& issue) {}
+ virtual void reportIssue(const std::string& sessionId,
+ const InterpreterIssue& issue) {}
void copyToInvokers(bool copy) {
_copyToInvokers = copy;
@@ -125,6 +147,277 @@ protected:
std::string _logPrefix;
};
+class USCXML_API LambdaMonitor : public InterpreterMonitor {
+public:
+ void processEvent(std::function<void (const std::string& sessionId,
+ const Event& event)> callback) {
+ _beforeProcessingEvent = callback;
+ }
+
+
+ void microStep(std::function<void (const std::string& sessionId)> callback,
+ bool after = false) {
+ if (after) {
+ _afterMicroStep = callback;
+ } else {
+ _beforeMicroStep = callback;
+ }
+
+ }
+
+ void exitState(std::function<void (const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state)> callback,
+ bool after = false) {
+ if (after) {
+ _afterExitingState = callback;
+ } else {
+ _beforeExitingState = callback;
+ }
+ }
+
+ void executeContent(std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* execContent)> callback,
+ bool after = false) {
+ if (after) {
+ _afterExecutingContent = callback;
+ } else {
+ _beforeExecutingContent = callback;
+ }
+ }
+
+ void uninvoke(std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid)> callback,
+ bool after = false) {
+ if (after) {
+ _afterUninvoking = callback;
+ } else {
+ _beforeUninvoking = callback;
+ }
+ }
+
+ void transition(std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* transition)> callback,
+ bool after = false) {
+ if (after) {
+ _afterTakingTransition = callback;
+ } else {
+ _beforeTakingTransition = callback;
+ }
+ }
+
+ void enterState(std::function<void (const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state)> callback,
+ bool after = false) {
+ _beforeEnteringState = callback;
+ if (after) {
+ _afterEnteringState = callback;
+ } else {
+ _beforeEnteringState = callback;
+ }
+
+ }
+
+ void invoke(std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid)> callback,
+ bool after = false) {
+ if (after) {
+ _afterInvoking = callback;
+ } else {
+ _beforeInvoking = callback;
+ }
+ }
+
+ void stableConfiguration(std::function<void (const std::string& sessionId)> callback) {
+ _onStableConfiguration = callback;
+ }
+
+ void completion(std::function<void (const std::string& sessionId)> callback,
+ bool after = false) {
+ if (after) {
+ _afterCompletion = callback;
+ } else {
+ _beforeCompletion = callback;
+ }
+
+ }
+
+ void reportIssue(std::function<void (const std::string& sessionId,
+ const InterpreterIssue& issue)> callback) {
+ _reportIssue = callback;
+ }
+
+protected:
+
+ std::function<void (const std::string& sessionId,
+ const Event& event)> _beforeProcessingEvent;
+
+ std::function<void (const std::string& sessionId)> _beforeMicroStep;
+
+ std::function<void (const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state)> _beforeExitingState;
+
+ std::function<void (const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state)> _afterExitingState;
+
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* execContent)> _beforeExecutingContent;
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* execContent)> _afterExecutingContent;
+
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid)> _beforeUninvoking;
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid)> _afterUninvoking;
+
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* transition)> _beforeTakingTransition;
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* transition)> _afterTakingTransition;
+
+ std::function<void (const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state)> _beforeEnteringState;
+ std::function<void (const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state)> _afterEnteringState;
+
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid)> _beforeInvoking;
+ std::function<void (const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid)> _afterInvoking;
+
+ std::function<void (const std::string& sessionId)> _afterMicroStep;
+ std::function<void (const std::string& sessionId)> _onStableConfiguration;
+
+ std::function<void (const std::string& sessionId)> _beforeCompletion;
+ std::function<void (const std::string& sessionId)> _afterCompletion;
+
+ std::function<void (const std::string& sessionId,
+ const InterpreterIssue& issue)> _reportIssue;
+
+
+
+ void beforeProcessingEvent(const std::string& sessionId,
+ const Event& event) {
+ if (_beforeProcessingEvent)
+ _beforeProcessingEvent(sessionId, event);
+ }
+ void beforeMicroStep(const std::string& sessionId) {
+ if (_beforeMicroStep)
+ _beforeMicroStep(sessionId);
+ }
+
+ void beforeExitingState(const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state) {
+ if (_beforeExitingState)
+ _beforeExitingState(sessionId, stateName, state);
+ }
+
+ void afterExitingState(const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state) {
+ if (_afterExitingState)
+ _afterExitingState(sessionId, stateName, state);
+ }
+
+ void beforeExecutingContent(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* execContent) {
+ if (_beforeExecutingContent)
+ _beforeExecutingContent(sessionId, execContent);
+ }
+ void afterExecutingContent(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* execContent) {
+ if (_afterExecutingContent)
+ _afterExecutingContent(sessionId, execContent);
+
+ }
+
+ void beforeUninvoking(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid) {
+ if (_beforeUninvoking)
+ _beforeUninvoking(sessionId, invokeElem, invokeid);
+ }
+ void afterUninvoking(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid) {
+ if (_afterUninvoking)
+ _afterUninvoking(sessionId, invokeElem, invokeid);
+ }
+
+ void beforeTakingTransition(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* transition) {
+ if (_beforeTakingTransition)
+ _beforeTakingTransition(sessionId, transition);
+ }
+ void afterTakingTransition(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* transition) {
+ if (_afterTakingTransition)
+ _afterTakingTransition(sessionId, transition);
+ }
+
+ void beforeEnteringState(const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state) {
+ if (_beforeEnteringState)
+ _beforeEnteringState(sessionId, stateName, state);
+ }
+ void afterEnteringState(const std::string& sessionId,
+ const std::string& stateName,
+ const XERCESC_NS::DOMElement* state) {
+ if (_afterEnteringState)
+ _afterEnteringState(sessionId, stateName, state);
+ }
+
+ void beforeInvoking(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid) {
+ if (_beforeInvoking)
+ _beforeInvoking(sessionId, invokeElem, invokeid);
+ }
+ void afterInvoking(const std::string& sessionId,
+ const XERCESC_NS::DOMElement* invokeElem,
+ const std::string& invokeid) {
+ if (_afterInvoking)
+ _afterInvoking(sessionId, invokeElem, invokeid);
+ }
+
+ void afterMicroStep(const std::string& sessionId) {
+ if (_afterMicroStep)
+ _afterMicroStep(sessionId);
+ }
+ void onStableConfiguration(const std::string& sessionId) {
+ if (_onStableConfiguration)
+ _onStableConfiguration(sessionId);
+ }
+
+ void beforeCompletion(const std::string& sessionId) {
+ if (_beforeCompletion)
+ _beforeCompletion(sessionId);
+ }
+ void afterCompletion(const std::string& sessionId) {
+ if (_afterCompletion)
+ _afterCompletion(sessionId);
+ }
+
+ void reportIssue(const std::string& sessionId,
+ const InterpreterIssue& issue) {
+ if (_reportIssue)
+ _reportIssue(sessionId, issue);
+ }
+};
+
}
#endif /* end of include guard: INTERPRETERMONITOR_H_D3F21429 */
diff --git a/src/uscxml/util/Predicates.cpp b/src/uscxml/util/Predicates.cpp
index 6649907..1f95a52 100644
--- a/src/uscxml/util/Predicates.cpp
+++ b/src/uscxml/util/Predicates.cpp
@@ -328,7 +328,6 @@ DOMElement* getState(const std::string& stateId, const DOMElement* root) {
}
// no state with such an id in document!
- assert(false);
return NULL;
}
diff --git a/test/src/test-snippets.cpp b/test/src/test-snippets.cpp
index f26b730..5eb680f 100644
--- a/test/src/test-snippets.cpp
+++ b/test/src/test-snippets.cpp
@@ -9,6 +9,8 @@
#include "uscxml/Interpreter.h"
#include "uscxml/interpreter/LoggingImpl.h"
+#include <iostream>
+
using namespace uscxml;
void microstep_snippet() {
@@ -31,9 +33,30 @@ void microstep_snippet() {
}
+void lambda_snippet() {
+ InterpreterState state = uscxml::USCXML_UNDEF;
+ Interpreter scxml = Interpreter::fromURL("https://raw.githubusercontent.com/tklab-tud/uscxml/master/test/w3c/null/test436.scxml");
+
+ scxml.on().enterState([](const std::string& sessionId,
+ const std::string& stateName,
+ const xercesc_3_1::DOMElement* state) {
+ std::cout << "Entered " << stateName << std::endl;
+ });
+
+ scxml.on().exitState([](const std::string& sessionId,
+ const std::string& stateName,
+ const xercesc_3_1::DOMElement* state) {
+ std::cout << "Exited " << stateName << std::endl;
+ });
+
+
+ while((state = scxml.step()) != uscxml::USCXML_FINISHED) {}
+
+}
+
int main(int argc, char** argv) {
try {
- Logger::getDefault().log(USCXML_FATAL) << "Foo!" << " BAR?" << std::endl;
+ lambda_snippet();
microstep_snippet();
} catch (...) {
exit(EXIT_FAILURE);