diff --git a/src/lib/thread-wrapper.hpp b/src/lib/thread-wrapper.hpp new file mode 100644 index 000000000..8c90295b4 --- /dev/null +++ b/src/lib/thread-wrapper.hpp @@ -0,0 +1,90 @@ +/* + THREADWRAPPER.hpp - thin convenience wrapper for starting lumiera threads + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef LUMIERA_THREADWRAPPER_H +#define LUMIERA_THREADWRAPPER_H + + +#include "backend/threads.h" +#include "include/nobugcfg.h" + +#include +#include + + +namespace lumiera { + + using std::tr1::bind; + using std::tr1::function; + using std::tr1::placeholders::_1; + + + /** + * A thin convenience wrapper for dealing with threads, + * as implemented by the backend (on top of pthread). + * Using this wrapper... + * - helps with passing data to the function executed in the new thread + * - allows to bind to various kinds of functions + * - supports integrating with an existing object monitor based lock (planned) + * + * @note this class is \em not a thread handle. Within Lumiera, we do all of + * our thread management such as to avoid using global thread handles. + * If some cooperation between threads is needed, this should be done + * in a implementation private way, e.g. by sharing a condition var. + * + * @todo Ichthyo started this wrapper 12/08 while our own thread handling + * was just being shaped. It may well be possible that such a wrapper + * is superfluous in the final application. Re-evaluate this! + */ + class Thread : boost::noncopyable + { + typedef function Operation; + + static void + run (void* arg) + { + ASSERT (arg); + Operation doIt_ = *reinterpret_cast(arg); + + doIt_(); + } + + + public: + Thread (Literal& purpose, Operation operation, struct nobug_flag *logging_flag = &NOBUG_FLAG(operate)) + { + lumiera_thread_run ( LUMIERA_THREAD_INTERACTIVE + , &run // invoking the run helper and.. + , &operation // passing the actual operation as parameter + , 0 // no condition variable provided (for now...) + , purpose.c_str() + , logging_flag + ); + } + }; + + + + +} // namespace lumiera +#endif diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index 5be9d86fc..0e9efe563 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -59,6 +59,7 @@ test_lib_SOURCES = \ $(testlib_srcdir)/singletontestmocktest.cpp \ $(testlib_srcdir)/streamtypebasicstest.cpp \ $(testlib_srcdir)/streamtypelifecycletest.cpp \ + $(testlib_srcdir)/subsystem-runner-test.cpp \ $(testlib_srcdir)/sync-classlock-test.cpp \ $(testlib_srcdir)/sync-locking-test.cpp \ $(testlib_srcdir)/sync-waiting-test.cpp \ diff --git a/tests/lib/subsystem-runner-test.cpp b/tests/lib/subsystem-runner-test.cpp index fb9564eaa..d53ba9865 100644 --- a/tests/lib/subsystem-runner-test.cpp +++ b/tests/lib/subsystem-runner-test.cpp @@ -26,9 +26,11 @@ #include "common/subsystem-runner.hpp" #include "include/symbol.hpp" +#include "lib/thread-wrapper.hpp" #include "lib/error.hpp" #include "lib/query.hpp" #include "lib/util.hpp" +#include "lib/sync.hpp" #include #include @@ -38,6 +40,8 @@ using std::tr1::bind; using std::tr1::placeholders::_1; using util::isnil; using test::Test; +using lib::Sync; +using lib::RecursiveLock_Waitable; namespace lumiera { @@ -67,18 +71,16 @@ namespace lumiera { */ class MockSys : public lumiera::Subsys, - public Sync + public Sync { - bool isUp_; Literal id_; Literal spec_; + bool isUp_; volatile bool termRequest_; int running_duration_; - operator string () const { return "MockSys(\""+id_+"\")"; } - bool shouldStart (lumiera::Option&) { @@ -100,7 +102,7 @@ namespace lumiera { if ("true"==startSpec) //----simulate successful subsystem start { - Thread (bind (&MockSys::run, this, termination)); + Thread (id_, bind (&MockSys::run, this, termination)); /////TODO: the thread description should be rather "Test: "+string(*this), but this requires to implement the class Literal as planned isUp_ = true; } else @@ -131,12 +133,13 @@ namespace lumiera { cout << *this << ": start running...\n"; Literal runSpec (extractID ("run",spec_)); - ASSERT (!isnil (startSpec)); + ASSERT (!isnil (runSpec)); if ("false"!=runSpec) //----actually hold running state for some time { running_duration_ = (rand() % MAX_RUNNING_TIME_ms); - Lock wait(this, &MockSys::tick); + + Lock wait_blocking (this, &MockSys::tick); } Error problemIndicator("simulated Problem killing a subsystem"); @@ -177,11 +180,14 @@ namespace lumiera { { } ~MockSys() { cout << *this << " dead.\n"; } + + operator string () const { return "MockSys(\""+id_+"\")"; } + + friend inline ostream& + operator<< (ostream& os, MockSys const& mosi) { return os << string(mosi); } + }; - - inline ostream& operator<< (ostream& os, MockSys const& mosi) { return os << string(mosi); } - } // (End) test classes and data....