summaryrefslogtreecommitdiff
path: root/src/TaskMan.cc
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-11-17 13:02:49 -0800
committerPixel <pixel@nobis-crew.org>2011-11-17 13:02:49 -0800
commitb9d76f0b574be1dcd991f26d9ca3d63e4b09731f (patch)
tree7edf6e9391d530f648f6dfb86e638367b0fb9131 /src/TaskMan.cc
parent2cb2961c9f6062e867b6ccc3d9067f55c7b81ea4 (diff)
And adding the round robin system to the task scheduler. Now to write some unit test for this...
Diffstat (limited to 'src/TaskMan.cc')
-rw-r--r--src/TaskMan.cc50
1 files changed, 42 insertions, 8 deletions
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
index 3a5cc1c..0980a3b 100644
--- a/src/TaskMan.cc
+++ b/src/TaskMan.cc
@@ -35,6 +35,8 @@ class TaskScheduler : public Thread, public AtStart, public AtExit {
void stopAll();
private:
Queue<Task *> m_queue;
+ std::queue<TaskMan *> m_taskManagers;
+ Lock m_lock;
volatile bool m_stopping;
};
@@ -48,18 +50,43 @@ void Balau::TaskScheduler::registerTask(Task * t) {
}
void Balau::TaskScheduler::registerTaskMan(TaskMan * t) {
- // meh. We need a round-robin queue system.
+ m_lock.enter();
+ m_taskManagers.push(t);
+ m_lock.leave();
}
void Balau::TaskScheduler::unregisterTaskMan(TaskMan * t) {
- // and here, we need to remove that taskman from the round robin queue.
+ m_lock.enter();
+ TaskMan * p = NULL;
+ // yes, this is a potentially dangerous operation.
+ // But unregistering task managers shouldn't happen that often.
+ while (true) {
+ p = m_taskManagers.front();
+ m_taskManagers.pop();
+ if (p == t)
+ break;
+ m_taskManagers.push(p);
+ }
+ m_lock.leave();
}
void Balau::TaskScheduler::stopAll() {
m_stopping = true;
- // and finally, we need to crawl the whole list and stop all of them.
- TaskMan * tm = localTaskMan.getGlobal();
- tm->addToPending(new Stopper());
+ m_lock.enter();
+ std::queue<TaskMan *> altQueue;
+ TaskMan * tm;
+ while (!m_taskManagers.empty()) {
+ tm = m_taskManagers.front();
+ m_taskManagers.pop();
+ altQueue.push(tm);
+ tm->addToPending(new Stopper());
+ }
+ while (!altQueue.empty()) {
+ tm = altQueue.front();
+ altQueue.pop();
+ m_taskManagers.push(tm);
+ }
+ m_lock.leave();
}
void * Balau::TaskScheduler::proc() {
@@ -70,9 +97,16 @@ void * Balau::TaskScheduler::proc() {
break;
if (dynamic_cast<Stopper *>(t) || m_stopping)
break;
- // pick up a task manager here... for now let's take the global one.
- // but we need some sort of round robin across all of the threads, as described above.
- TaskMan * tm = localTaskMan.getGlobal();
+ m_lock.enter();
+ size_t s = m_taskManagers.size();
+ if (s == 0)
+ break;
+ TaskMan * tm = m_taskManagers.front();
+ if (s != 1) {
+ m_taskManagers.pop();
+ m_taskManagers.push(tm);
+ }
+ 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();