summaryrefslogtreecommitdiff
path: root/lib/TaskMan.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/TaskMan.cc')
-rw-r--r--lib/TaskMan.cc65
1 files changed, 54 insertions, 11 deletions
diff --git a/lib/TaskMan.cc b/lib/TaskMan.cc
index 83fe5aa..fd630d8 100644
--- a/lib/TaskMan.cc
+++ b/lib/TaskMan.cc
@@ -51,6 +51,8 @@ Handle * TaskMan::ehandle;
sigset_t TaskMan::sigchildset;
+Atomic::Queue<Task> TaskMan::new_tasks;
+
#ifndef _WIN32
void taskman_sigchild(int sig) {
TaskMan::SigChild();
@@ -382,9 +384,16 @@ void TaskMan::AddTask(Task * t) {
Init();
}
- if (t) {
- TaskList.push_back(t);
- number++;
+ if (t)
+ new_tasks.enqueue(t);
+}
+
+void TaskMan::ProcessNewTasks() {
+ Task * t;
+
+ while(new_tasks.unqueue(&t)) {
+ TaskList.push_back(t);
+ number++;
}
}
@@ -524,13 +533,14 @@ void TaskMan::MainLoop() throw (GeneralException) {
struct pollfd * ufsd;
unsigned int nfds;
- int no_burst;
+ bool no_burst, no_idle;
if (!inited) {
Init();
}
-
- while (1) {
+
+ while (true) {
+ ProcessNewTasks();
if (number == 0) {
throw GeneralException(_("TaskMan: No more task to manage."));
}
@@ -545,15 +555,17 @@ void TaskMan::MainLoop() throw (GeneralException) {
if (!TaskList.empty()) {
for (TaskList_t::iterator p = TaskList.begin(); p != TaskList.end(); p++) {
Task * t = *p;
+ if (t->GetState() == Task::TASK_IDLE_REST)
+ t->SetIdle();
// cerr << "-=- TaskMan: task " << t->GetName() << endl;
}
}
// cerr << "-=- TaskMan: processing burning tasks.\n";
- no_burst = 0;
+ no_burst = false;
while (!no_burst) {
- no_burst = 1;
+ no_burst = true;
/* First, we will check for any burning task and run 'em */
event = Task::EVT_BURST;
if (!TaskList.empty()) {
@@ -578,7 +590,38 @@ void TaskMan::MainLoop() throw (GeneralException) {
t->BurstHandle = 0;
}
/* if the task added some new tasks, we have to rerun the loop */
- no_burst = 0;
+ no_burst = false;
+ break;
+ }
+
+ // Additionnally, if the task died, let's put it in the zombies list.
+ // This check is done on the whole TaskList at each loop.
+ if (CheckDead(t))
+ p = TaskList.begin();
+ }
+ }
+ }
+
+ no_idle = false;
+ while (!no_idle) {
+ no_idle = true;
+ /* First, we will check for any idle task and run 'em */
+ event = Task::EVT_IDLE;
+ if (!TaskList.empty()) {
+ for (TaskList_t::iterator p = TaskList.begin(); p != TaskList.end(); p++) {
+ Task * t = *p;
+
+ if (t->IsStopped()) {
+ continue;
+ }
+
+ if (t->GetState() == Task::TASK_IDLE) {
+// cerr << "-=- TaskMan: running idle task " << t->GetName() << endl;
+ t->Run();
+ /* if the task added some new tasks, we have to rerun the loop */
+ no_idle = false;
+ /* and toggle the task so it's not running through the loop again. */
+ t->IdleRest();
break;
}
@@ -647,7 +690,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
event = Task::EVT_HANDLE;
nfds = w4ha.size();
- no_burst = 1;
+ no_burst = true;
if (nfds != 0) {
int r;
@@ -672,7 +715,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
// considering it already processed for this handle loop.
// It'll be run immediately next cycle.
p->T->SetBurst();
- no_burst = 0;
+ no_burst = false;
p->dirty = true;
q->fd = 0;
q->events = 0;