#include <signal.h>
#include <time.h>
#include "../Utils/Exception.hh"
+#include "../Utils/senfassert.hh"
//#include "FIFORunner.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ senf::scheduler::FIFORunner::FIFORunner()
+prefix_ senf::scheduler::detail::FIFORunner::FIFORunner()
: tasks_ (), next_ (tasks_.end()), watchdogMs_ (1000), watchdogCount_(0), hangCount_ (0)
{
struct sigevent ev;
SENF_THROW_SYSTEM_EXCEPTION("sigprocmask()");
}
-prefix_ senf::scheduler::FIFORunner::~FIFORunner()
+prefix_ senf::scheduler::detail::FIFORunner::~FIFORunner()
{
timer_delete(watchdogId_);
signal(SIGURG, SIG_DFL);
// will mostly be localized to the end of the queue. only occasionally one of the dormant tasks will
// be runnable. This additional traversal time will be amortized over a larger time.
-prefix_ void senf::scheduler::FIFORunner::dequeue(TaskInfo * task)
+prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task)
{
TaskList::iterator i (TaskList::current(*task));
if (next_ == i)
namespace {
struct NullTask
- : public senf::scheduler::FIFORunner::TaskInfo
+ : public senf::scheduler::detail::FIFORunner::TaskInfo
{
- void run() {};
+ NullTask() : senf::scheduler::detail::FIFORunner::TaskInfo ("<null>") {}
+ virtual void v_run() {};
+ virtual char const * v_type() const { return 0; }
+ virtual std::string v_info() const { return ""; }
};
}
-prefix_ void senf::scheduler::FIFORunner::run()
+prefix_ void senf::scheduler::detail::FIFORunner::run()
{
// This algorithm is carefully adjusted to make it work even when arbitrary tasks are removed
// from the queue
// - We keep the next to-be-processed node in a class variable which is checked and updated
// whenever a node is removed.
NullTask null;
- tasks_.push_back(null);
- TaskList::iterator end (TaskList::current(null));
- next_ = tasks_.begin();
struct itimerspec timer;
timer.it_interval.tv_sec = watchdogMs_ / 1000;
timer.it_interval.tv_nsec = (watchdogMs_ % 1000) * 1000000ul;
timer.it_value.tv_sec = timer.it_interval.tv_sec;
timer.it_value.tv_nsec = timer.it_interval.tv_nsec;
- if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
- SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
- while (next_ != end) {
- TaskInfo & task (*next_);
- if (task.runnable) {
- task.runnable = false;
- runningName_ = task.name;
-# ifdef SENF_DEBUG
- runningBacktrace_ = task.backtrace;
-# endif
- TaskList::iterator i (next_);
- ++ next_;
- tasks_.splice(tasks_.end(), tasks_, i);
- watchdogCount_ = 1;
- task.run();
+ tasks_.push_back(null);
+ TaskList::iterator end (TaskList::current(null));
+ next_ = tasks_.begin();
+ try {
+ if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+ SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
+ while (next_ != end) {
+ TaskInfo & task (*next_);
+ if (task.runnable_) {
+ task.runnable_ = false;
+ runningName_ = task.name();
+# ifdef SENF_DEBUG
+ runningBacktrace_ = task.backtrace_;
+# endif
+ TaskList::iterator i (next_);
+ ++ next_;
+ tasks_.splice(tasks_.end(), tasks_, i);
+ watchdogCount_ = 1;
+ task.run();
+ }
+ else
+ ++ next_;
}
- else
- ++ next_;
+ }
+ catch (...) {
+ watchdogCount_ = 0;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_nsec = 0;
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_nsec = 0;
+ timer_settime(watchdogId_, 0, &timer, 0);
+ tasks_.erase(end);
+ next_ = tasks_.end();
+ throw;
}
watchdogCount_ = 0;
timer.it_interval.tv_sec = 0;
next_ = tasks_.end();
}
-prefix_ void senf::scheduler::FIFORunner::watchdog(int, siginfo_t * si, void *)
+prefix_ void senf::scheduler::detail::FIFORunner::watchdog(int, siginfo_t * si, void *)
{
FIFORunner & runner (*static_cast<FIFORunner *>(si->si_value.sival_ptr));
if (runner.watchdogCount_ > 0) {