From 9bdb93b01b037358a209af040b561fca3a51851b Mon Sep 17 00:00:00 2001 From: Pixel Date: Fri, 6 Apr 2012 10:38:13 -0700 Subject: A few improvements over how a threaded TaskMan works. Now its own exported class. Also has a proper exception handling in its caller. --- includes/TaskMan.h | 17 ++++++++++++-- src/TaskMan.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/includes/TaskMan.h b/includes/TaskMan.h index 088d5d7..6c446b7 100644 --- a/includes/TaskMan.h +++ b/includes/TaskMan.h @@ -25,6 +25,15 @@ class Async; class TaskMan { public: + class TaskManThread : public Thread { + public: + virtual ~TaskManThread(); + virtual void * proc(); + void stopMe(int code = 0) { m_taskMan->stopMe(code); } + private: + TaskMan * m_taskMan; + }; + TaskMan(); ~TaskMan(); int mainLoop(); @@ -32,8 +41,12 @@ class TaskMan { struct ev_loop * getLoop() { return m_loop; } void signalTask(Task * t); static void stop(int code); - void stopMe(int code) { m_stopped = true; m_stopCode = code; } - static Thread * createThreadedTaskMan(); + void stopMe(int code = 0); + static TaskManThread * createThreadedTaskMan() { + TaskManThread * r = new TaskManThread(); + r->threadStart(); + return r; + } bool stopped() { return m_stopped; } template static T * createTask(T * t, Task * stick = NULL) { TaskMan::registerTask(t, stick); return t; } diff --git a/src/TaskMan.cc b/src/TaskMan.cc index e663873..0f205cf 100644 --- a/src/TaskMan.cc +++ b/src/TaskMan.cc @@ -85,7 +85,6 @@ void Balau::TaskScheduler::stopAll(int code) { m_taskManagers.pop(); altQueue.push(tm); tm->addToPending(new Stopper(code)); - tm->m_evt.send(); } while (!altQueue.empty()) { tm = altQueue.front(); @@ -114,7 +113,6 @@ void * Balau::TaskScheduler::proc() { m_lock.leave(); Printer::elog(E_TASK, "TaskScheduler popped task %s at %p; adding to TaskMan %p", t->getName(), t, tm); tm->addToPending(t); - tm->m_evt.send(); } Printer::elog(E_TASK, "TaskScheduler stopping."); return NULL; @@ -129,6 +127,16 @@ void asyncDummy(ev::async & w, int revents) { Balau::Printer::elog(Balau::E_TASK, "TaskMan is getting woken up..."); } +void Balau::TaskMan::stopMe(int code) { + Task * t = Task::getCurrentTask(); + if (t->getTaskMan() == this) { + m_stopped = true; + m_stopCode = code; + } else { + addToPending(new Stopper(code)); + } +} + Balau::TaskMan::TaskMan() : m_stopped(false), m_allowedToSignal(false), m_stopCode(0) { #ifndef _WIN32 coro_create(&m_returnContext, 0, 0, 0, 0); @@ -179,6 +187,7 @@ Balau::TaskMan::~TaskMan() { } s_scheduler.unregisterTaskMan(this); // probably way more work to do here in order to clean up tasks from that thread + m_evt.stop(); ev_loop_destroy(m_loop); } @@ -221,6 +230,8 @@ int Balau::TaskMan::mainLoop() { // checking "STARTING" tasks, and running them once while ((iH = starting.begin()) != starting.end()) { Task * t = *iH; + if (t->getStatus() != Task::STARTING) + Printer::elog(E_TASK, "pouet"); IAssert(t->getStatus() == Task::STARTING, "Got task at %p in the starting list, but isn't starting.", t); t->switchTo(); IAssert(t->getStatus() != Task::STARTING, "Task at %p got switchedTo, but still is 'STARTING'.", t); @@ -324,7 +335,6 @@ void Balau::TaskMan::registerTask(Balau::Task * t, Balau::Task * stick) { if (stick) { TaskMan * tm = stick->getTaskMan(); tm->addToPending(t); - tm->m_evt.send(); } else { s_scheduler.registerTask(t); } @@ -332,6 +342,7 @@ void Balau::TaskMan::registerTask(Balau::Task * t, Balau::Task * stick) { void Balau::TaskMan::addToPending(Balau::Task * t) { m_pendingAdd.push(t); + m_evt.send(); } void Balau::TaskMan::signalTask(Task * t) { @@ -344,17 +355,49 @@ void Balau::TaskMan::stop(int code) { s_scheduler.stopAll(code); } -class ThreadedTaskMan : public Balau::Thread { - virtual void * proc() { - m_taskMan = new Balau::TaskMan(); +void * Balau::TaskMan::TaskManThread::proc() { + m_taskMan = new Balau::TaskMan(); + bool success = false; + try { m_taskMan->mainLoop(); - return NULL; + success = true; } - Balau::TaskMan * m_taskMan; -}; + catch (Exit e) { + Printer::log(M_ERROR, "We shouldn't have gotten an Exit exception here... exitting anyway"); + auto trace = e.getTrace(); + for (String & str : trace) + Printer::log(M_ERROR, "%s", str.to_charp()); + } + catch (RessourceException e) { + Printer::log(M_ERROR | M_ALERT, "The TaskMan thread got a ressource problem: %s", e.getMsg()); + const char * details = e.getDetails(); + if (details) + Printer::log(M_ERROR, " %s", details); + auto trace = e.getTrace(); + for (String & str : trace) + Printer::log(M_DEBUG, "%s", str.to_charp()); + } + catch (GeneralException e) { + Printer::log(M_ERROR | M_ALERT, "The TaskMan thread caused an exception: %s", e.getMsg()); + const char * details = e.getDetails(); + if (details) + Printer::log(M_ERROR, " %s", details); + auto trace = e.getTrace(); + for (String & str : trace) + Printer::log(M_DEBUG, "%s", str.to_charp()); + } + catch (...) { + Printer::log(M_ERROR | M_ALERT, "The TaskMan thread caused an unknown exception"); + } + if (!success) { + delete m_taskMan; + m_taskMan = NULL; + TaskMan::stop(-1); + } + return NULL; +} -Balau::Thread * Balau::TaskMan::createThreadedTaskMan() { - Thread * r = new ThreadedTaskMan(); - r->threadStart(); - return r; +Balau::TaskMan::TaskManThread::~TaskManThread() { + if (m_taskMan) + delete m_taskMan; } -- cgit v1.2.3