summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/Jamfile.jam2
-rw-r--r--libadhocutil/runtimeContext.cpp38
-rw-r--r--libadhocutil/runtimeContext.h28
-rw-r--r--libadhocutil/unittests/Jamfile.jam19
-rw-r--r--libadhocutil/unittests/testContext.cpp34
5 files changed, 121 insertions, 0 deletions
diff --git a/libadhocutil/Jamfile.jam b/libadhocutil/Jamfile.jam
index 8169ad0..b689242 100644
--- a/libadhocutil/Jamfile.jam
+++ b/libadhocutil/Jamfile.jam
@@ -26,5 +26,7 @@ lib adhocutil :
<include>.
;
+build-project unittests ;
+
package.install install : <install-source-root>. : : adhocutil : [ glob *.h ] ;
diff --git a/libadhocutil/runtimeContext.cpp b/libadhocutil/runtimeContext.cpp
new file mode 100644
index 0000000..f4e12c2
--- /dev/null
+++ b/libadhocutil/runtimeContext.cpp
@@ -0,0 +1,38 @@
+#include "runtimeContext.h"
+#include <stdexcept>
+
+RuntimeContext::RuntimeContext(size_t stacksize) :
+ swapped(false)
+{
+ stack = malloc(stacksize);
+ if (getcontext(&callback) == -1)
+ throw std::runtime_error("Failed to getcontext");
+ callback.uc_stack.ss_sp = stack;
+ callback.uc_stack.ss_size = stacksize;
+ callback.uc_link = &initial;
+ makecontext(&callback, (void (*)())&RuntimeContext::ccallback, 1, this);
+}
+
+RuntimeContext::~RuntimeContext()
+{
+ free(stack);
+}
+
+void
+RuntimeContext::SwapContext()
+{
+ swapped = !swapped;
+ if (swapped) {
+ swapcontext(&initial, &callback);
+ }
+ else {
+ swapcontext(&callback, &initial);
+ }
+}
+
+void
+RuntimeContext::ccallback(RuntimeContext * rc)
+{
+ rc->Callback();
+}
+
diff --git a/libadhocutil/runtimeContext.h b/libadhocutil/runtimeContext.h
new file mode 100644
index 0000000..6fe26f0
--- /dev/null
+++ b/libadhocutil/runtimeContext.h
@@ -0,0 +1,28 @@
+#ifndef ADHOCUTIL_RUNTIMECONTEXT_H
+#define ADHOCUTIL_RUNTIMECONTEXT_H
+
+#include <stdlib.h>
+#include <ucontext.h>
+#include "visibility.h"
+
+class DLL_PUBLIC RuntimeContext {
+ public:
+ RuntimeContext(size_t stacksize = 16384);
+ virtual ~RuntimeContext();
+
+ void SwapContext();
+
+ protected:
+ DLL_PRIVATE virtual void Callback() = 0;
+
+ private:
+ DLL_PRIVATE static void ccallback(RuntimeContext * rc);
+
+ void * stack;
+ ucontext_t initial;
+ ucontext_t callback;
+ bool swapped;
+};
+
+#endif
+
diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam
new file mode 100644
index 0000000..65d8fad
--- /dev/null
+++ b/libadhocutil/unittests/Jamfile.jam
@@ -0,0 +1,19 @@
+import testing ;
+
+path-constant me : . ;
+
+lib boost_utf : : <name>boost_unit_test_framework ;
+lib boost_filesystem ;
+lib boost_system ;
+
+run
+ testContext.cpp
+ : : :
+ <define>ROOT=\"$(me)\"
+ <define>BOOST_TEST_DYN_LINK
+ <library>..//adhocutil
+ <library>boost_utf
+ :
+ testContext
+ ;
+
diff --git a/libadhocutil/unittests/testContext.cpp b/libadhocutil/unittests/testContext.cpp
new file mode 100644
index 0000000..6a291bf
--- /dev/null
+++ b/libadhocutil/unittests/testContext.cpp
@@ -0,0 +1,34 @@
+#define BOOST_TEST_MODULE Context
+#include <boost/test/unit_test.hpp>
+
+#include "runtimeContext.h"
+
+class testRuntimeContext : RuntimeContext {
+ public:
+ void Run()
+ {
+ log += "a";
+ SwapContext();
+ log += "b";
+ SwapContext();
+ log += "c";
+ }
+
+ void Callback() override
+ {
+ log += "d";
+ SwapContext();
+ log += "e";
+ SwapContext();
+ }
+
+ std::string log;
+};
+
+BOOST_AUTO_TEST_CASE ( basic )
+{
+ testRuntimeContext trc;
+ trc.Run();
+ BOOST_REQUIRE_EQUAL("adbec", trc.log);
+}
+