diff --git a/PPI/Module.test.cc b/PPI/Module.test.cc index ca678443d48da2073151d34f9fd63d3bdb791421..2f6df29839a26bdbaae6475e4c39b52920f8b25d 100644 --- a/PPI/Module.test.cc +++ b/PPI/Module.test.cc @@ -27,6 +27,8 @@ //#include "Module.test.ih" // Custom includes +#include <boost/scoped_ptr.hpp> +#include "../Utils/membind.hh" #include "DebugEvent.hh" #include "DebugModules.hh" #include "Setup.hh" @@ -80,6 +82,57 @@ BOOST_AUTO_UNIT_TEST(module) BOOST_CHECK( senf::ClockService::now() - tester.time() < senf::ClockService::seconds(1) ); } +namespace { + + void timeout() { + senf::scheduler::terminate(); + } + + class InitTest : public ppi::module::Module + { + SENF_PPI_MODULE(InitTest); + public: + InitTest() : init (false) {} + void v_init() { init = true; } + + bool init; + }; + + struct MakeInit { + boost::scoped_ptr<InitTest> tester; + void make() { + tester.reset(new InitTest()); + } + void test() { + BOOST_REQUIRE( tester ); + BOOST_CHECK( tester->init ); + } + }; + +} + +BOOST_AUTO_UNIT_TEST(delayedInit) +{ + MakeInit maker; + senf::scheduler::TimerEvent timer ( + "delayedInit timer", + senf::membind(&MakeInit::make, &maker), + senf::ClockService::now() + senf::ClockService::milliseconds(250) ); + senf::scheduler::TimerEvent testTimer ( + "delayedInit test", + senf::membind(&MakeInit::test, &maker), + senf::ClockService::now() + senf::ClockService::milliseconds(500) ); + senf::scheduler::TimerEvent timeoutTimer ( + "delayedInit timeout", + &timeout, + senf::ClockService::now() + senf::ClockService::milliseconds(750) ); + + senf::ppi::run(); + + BOOST_REQUIRE( maker.tester ); + BOOST_CHECK( maker.tester->init ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/PPI/ModuleManager.cc b/PPI/ModuleManager.cc index 0aab808b44543b64ae4c4cc76834f61bcf6fee3d..d5a64f771e5e840afff886315d3350a9c24894a1 100644 --- a/PPI/ModuleManager.cc +++ b/PPI/ModuleManager.cc @@ -71,7 +71,7 @@ prefix_ void senf::ppi::ModuleManager::run() prefix_ senf::ppi::ModuleManager::ModuleManager() : running_(false), terminate_(false), initRunner_ ("senf::ppi::init", membind(&ModuleManager::init, this), false, - scheduler::EventHook::POST) + scheduler::EventHook::PRE) {} ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/PPI/ModuleManager.cci b/PPI/ModuleManager.cci index db78d8572f691169f3d4e510540c73f5fac6ec1f..9bdc778b7694cbc053888e026239dd59fc1ff445 100644 --- a/PPI/ModuleManager.cci +++ b/PPI/ModuleManager.cci @@ -54,6 +54,10 @@ prefix_ void senf::ppi::ModuleManager::registerInitializable(Initializable & i) { initQueue_.push_back(&i); initRunner_.enable(); + // This call ensures, that the senf::ppi::init() handler is called as next handler + // after this handler returns (this works since the senf::ppi::init() handler is registered as + // PRE hook and thus has very high priority) + senf::scheduler::yield(); } prefix_ void senf::ppi::ModuleManager::unregisterInitializable(Initializable & i) diff --git a/PPI/Route.test.cc b/PPI/Route.test.cc index 233fab135bfe7548013a792af4f4c74927b4e56c..68e7ffdafc6d1c62bb92f1a8902211608a6d8d03 100644 --- a/PPI/Route.test.cc +++ b/PPI/Route.test.cc @@ -27,6 +27,7 @@ //#include "Route.test.ih" // Custom includes +#include <boost/scoped_ptr.hpp> #include "Route.hh" #include "DebugEvent.hh" #include "DebugModules.hh" @@ -36,6 +37,7 @@ #include "Joins.hh" #include "PassiveQueue.hh" #include "../Utils/membind.hh" +#include "../Utils/senfassert.hh" #include "../Utils/auto_unit_test.hh" #include <boost/test/test_tools.hpp> @@ -190,9 +192,10 @@ namespace { ModuleConnector( module::PriorityJoin & join) : join_( join) {}; void connect() { - module::PassiveQueue * queue = new module::PassiveQueue; + queue.reset(new module::PassiveQueue); ppi::connect( *queue, join_, 0); } + boost::scoped_ptr<module::PassiveQueue> queue; }; class TestSink : public module::Module @@ -206,7 +209,7 @@ namespace { } private: void request() { - (void) input.read().data(); + SENF_ASSERT(input()); } }; } @@ -217,26 +220,24 @@ BOOST_AUTO_UNIT_TEST(connect_runtime) module::ActiveFeeder feeder; module::PriorityJoin join; module::CloneSource source1 (senf::DataPacket::create()); - module::PassiveQueue queue; - ppi::connect( feeder, sink); - ppi::connect( join, feeder); ppi::connect( source1, join); + ppi::connect( join, feeder); + ppi::connect( feeder, sink); ModuleConnector moduleConnector ( join); - senf::scheduler::TimerEvent timer ( "connect_runtime timer", - senf::membind(&ModuleConnector::connect, moduleConnector), - senf::ClockService::now() + senf::ClockService::milliseconds(25)); + senf::scheduler::TimerEvent timer ( + "connect_runtime timer", + senf::membind(&ModuleConnector::connect, &moduleConnector), + senf::ClockService::now() + senf::ClockService::milliseconds(250)); senf::scheduler::TimerEvent timeoutTimer ( "connect_runtime test timeoutTimer", &timeout, - senf::ClockService::now() + senf::ClockService::milliseconds(50)); + senf::ClockService::now() + senf::ClockService::milliseconds(500)); -// senf::ppi::run(); + senf::ppi::run(); } - - ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Scheduler/EventHook.cci b/Scheduler/EventHook.cci index fd0e3046a74fb6d39309481d6152173a1fd40bc5..89e1b1a10b38d6ec31dd344a49b4c2f62c6cdb0c 100644 --- a/Scheduler/EventHook.cci +++ b/Scheduler/EventHook.cci @@ -56,8 +56,10 @@ prefix_ void senf::scheduler::EventHook::disable() prefix_ void senf::scheduler::EventHook::enable() { - if (! enabled()) + if (! enabled()) { detail::EventHookDispatcher::instance().add(*this); + setRunnable(); + } } prefix_ void senf::scheduler::EventHook::action(Callback const & cb) diff --git a/Scheduler/FIFORunner.cc b/Scheduler/FIFORunner.cc index a6fb824aa8be3d061285f19df8ad9b2a091236b0..2f37b91607c7b8042f30bb98f934e8404105a1ac 100644 --- a/Scheduler/FIFORunner.cc +++ b/Scheduler/FIFORunner.cc @@ -40,7 +40,7 @@ prefix_ senf::scheduler::detail::FIFORunner::FIFORunner() : tasks_ (), next_ (tasks_.end()), watchdogRunning_ (false), watchdogMs_ (1000), - watchdogAbort_ (false), watchdogCount_(0), hangCount_ (0) + watchdogAbort_ (false), watchdogCount_(0), hangCount_ (0), yield_ (false) { struct sigevent ev; ::memset(&ev, 0, sizeof(ev)); @@ -134,17 +134,32 @@ prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task) prefix_ void senf::scheduler::detail::FIFORunner::run() { - TaskList::iterator f (tasks_.begin()); - TaskList::iterator l (TaskList::current(highPriorityEnd_)); - run(f, l); + for(;;) { + TaskList::iterator f (tasks_.begin()); + TaskList::iterator l (TaskList::current(highPriorityEnd_)); + run(f, l); + if (yield_) { + yield_ = false; + continue; + } - f = l; ++f; - l = TaskList::current(normalPriorityEnd_); - run(f, l); - - f = l; ++f; - l = tasks_.end(); - run(f, l); + f = l; ++f; + l = TaskList::current(normalPriorityEnd_); + run(f, l); + if (yield_) { + yield_ = false; + continue; + } + + f = l; ++f; + l = tasks_.end(); + run(f, l); + if (yield_) { + yield_ = false; + continue; + } + break; + } } prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, TaskList::iterator l) @@ -172,7 +187,7 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task ScopeExit atExit (( var(watchdogCount_) = 0, var(next_) = l - )); + )); while (next_ != end) { TaskInfo & task (*next_); @@ -186,7 +201,10 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task ++ next_; tasks_.splice(l, tasks_, i); watchdogCount_ = 1; + yield_ = false; task.run(); + if (yield_) + return; } else ++ next_; diff --git a/Scheduler/FIFORunner.cci b/Scheduler/FIFORunner.cci index 5eea9000a777120fa67c06d5607fd4f9e3770a99..0ddc8899908be3a1eaaf70c6b68d9ae6f6270006 100644 --- a/Scheduler/FIFORunner.cci +++ b/Scheduler/FIFORunner.cci @@ -158,6 +158,11 @@ prefix_ senf::scheduler::detail::FIFORunner::iterator senf::scheduler::detail::F EventManager::IteratorFilter(), tasks_.end(), tasks_.end()); } +prefix_ void senf::scheduler::detail::FIFORunner::yield() +{ + yield_ = true; +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Scheduler/FIFORunner.hh b/Scheduler/FIFORunner.hh index 39e2e3a6a8801d4ce5a163aa4df6347395008b84..6513f72396485bc575b2e800e995376db6438915 100644 --- a/Scheduler/FIFORunner.hh +++ b/Scheduler/FIFORunner.hh @@ -110,6 +110,8 @@ namespace detail { iterator begin() const; iterator end() const; + void yield(); + protected: private: @@ -146,6 +148,7 @@ namespace detail { # endif unsigned watchdogCount_; unsigned hangCount_; + bool yield_; friend void senf::scheduler::restart(); friend class singleton<FIFORunner>; diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 9ea0e481ea8f57df5f98fe04ae167e537c557761..a79307ac5ca989e8ccc909552429e078672dcb0b 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -49,6 +49,11 @@ prefix_ void senf::scheduler::terminate() terminate_ = true; } +prefix_ void senf::scheduler::yield() +{ + senf::scheduler::detail::FIFORunner::instance().yield(); +} + prefix_ bool senf::scheduler::running() { return running_; diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 9f3d3cd2f3715f9c0156a9c5c1c9d8409c62c955..62a687ce5f39cea447d7228642a5abff0069b5f8 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -245,6 +245,13 @@ namespace scheduler { */ void terminate(); + /** \brief Immediately rescheduler + + Calling yield() will cause the scheduler to terminate the current queue run and immediately + rescheduler all pending tasks. + */ + void yield(); + /** \brief Return timestamp of last event This is the timestamp, the last event has been signaled. This is the real time at which the