From 734d503b78f8983cf7430d707fbdf938dadf6124 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 28 Aug 2015 00:35:44 +0100 Subject: Add RuntimeContext for easy context switching --- libadhocutil/Jamfile.jam | 2 ++ libadhocutil/runtimeContext.cpp | 38 ++++++++++++++++++++++++++++++++++ libadhocutil/runtimeContext.h | 28 +++++++++++++++++++++++++ libadhocutil/unittests/Jamfile.jam | 19 +++++++++++++++++ libadhocutil/unittests/testContext.cpp | 34 ++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+) create mode 100644 libadhocutil/runtimeContext.cpp create mode 100644 libadhocutil/runtimeContext.h create mode 100644 libadhocutil/unittests/Jamfile.jam create mode 100644 libadhocutil/unittests/testContext.cpp 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 : . ; +build-project unittests ; + package.install install : . : : 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 + +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 +#include +#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 : : boost_unit_test_framework ; +lib boost_filesystem ; +lib boost_system ; + +run + testContext.cpp + : : : + ROOT=\"$(me)\" + BOOST_TEST_DYN_LINK + ..//adhocutil + 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 + +#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); +} + -- cgit v1.2.3