From 1d9def9edae0011eeee8f83dc32fb3797ca2f46b Mon Sep 17 00:00:00 2001
From: Pixel <pixel@nobis-crew.org>
Date: Fri, 7 Oct 2011 15:36:12 -0700
Subject: More work in the Task manager. Also fixing a few bugs linked with the
 printer and TLS. Removed flto from compilation flags: this actually creates
 bad code (!)

---
 src/Printer.cc | 19 ++++++++++++++++---
 src/Task.cc    |  9 ++++++++-
 src/TaskMan.cc | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 71 insertions(+), 5 deletions(-)

(limited to 'src')

diff --git a/src/Printer.cc b/src/Printer.cc
index cb94084..ef0cbf5 100644
--- a/src/Printer.cc
+++ b/src/Printer.cc
@@ -19,6 +19,10 @@ Balau::Printer::Printer() : m_verbosity(M_STATUS | M_WARNING | M_ERROR) {
         localPrinter.setGlobal(this);
 }
 
+void Balau::Printer::setLocal() {
+    localPrinter.set(this);
+}
+
 Balau::Printer * Balau::Printer::getPrinter() { return localPrinter.get(); }
 
 void Balau::Printer::_log(uint32_t level, const char * fmt, va_list ap) {
@@ -31,11 +35,20 @@ void Balau::Printer::_log(uint32_t level, const char * fmt, va_list ap) {
         if (l & level)
             break;
 
-    print(prefixes[i]);
-    print(fmt, ap);
-    print("\n");
+    Printer * printer = getPrinter();
+
+    printer->_print(prefixes[i]);
+    printer->_print(fmt, ap);
+    printer->_print("\n");
 }
 
 void Balau::Printer::_print(const char * fmt, va_list ap) {
     vfprintf(stderr, fmt, ap);
 }
+
+void Balau::Printer::_print(const char * fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    _print(fmt, ap);
+    va_end(ap);
+}
diff --git a/src/Task.cc b/src/Task.cc
index d41f088..9bdad0c 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -9,10 +9,16 @@ Balau::Task::Task() {
     stack = malloc(size);
     coro_create(&ctx, coroutine, this, stack, size);
     taskMan = TaskMan::getTaskMan();
+    taskMan->registerTask(this);
     tls = tlsManager->createTLS();
     status = STARTING;
 }
 
+Balau::Task::~Task() {
+    free(stack);
+    free(tls);
+}
+
 void Balau::Task::coroutine(void * arg) {
     Task * task = reinterpret_cast<Task *>(arg);
     Assert(task);
@@ -38,7 +44,8 @@ void Balau::Task::switchTo() {
     tlsManager->setTLS(tls);
     coro_transfer(&taskMan->returnContext, &ctx);
     tlsManager->setTLS(oldTLS);
-    status = IDLE;
+    if (status == RUNNING)
+        status = IDLE;
 }
 
 void Balau::Task::suspend() {
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
index 783c683..bbaf35c 100644
--- a/src/TaskMan.cc
+++ b/src/TaskMan.cc
@@ -1,11 +1,12 @@
 #include "TaskMan.h"
+#include "Task.h"
 #include "Main.h"
 #include "Local.h"
 
 static Balau::DefaultTmpl<Balau::TaskMan> defaultTaskMan(50);
 static Balau::LocalTmpl<Balau::TaskMan> localTaskMan;
 
-Balau::TaskMan::TaskMan() {
+Balau::TaskMan::TaskMan() : stopped(false) {
     coro_create(&returnContext, 0, 0, 0, 0);
     if (!localTaskMan.getGlobal())
         localTaskMan.setGlobal(this);
@@ -18,4 +19,49 @@ Balau::TaskMan::~TaskMan() {
 }
 
 void Balau::TaskMan::mainLoop() {
+    // We need at least one round before bailing :)
+    do {
+        taskList::iterator i;
+        Task * t;
+
+        // lock pending
+        // Adding tasks that were added, maybe from other threads
+        for (i = pendingAdd.begin(); i != pendingAdd.end(); i++) {
+            Assert(tasks.find(*i) == tasks.end());
+            tasks.insert(*i);
+        }
+        pendingAdd.clear();
+        // unlock pending
+
+        // checking "STARTING" tasks, and running them once
+        for (i = tasks.begin(); i != tasks.end(); i++) {
+            t = *i;
+            if (t->getStatus() == Task::STARTING) {
+                t->switchTo();
+            }
+        }
+
+        // That's probably where we poll for events
+
+        // checking "STOPPED" tasks, and destroying them
+        bool didDelete;
+        do {
+            didDelete = false;
+            for (i = tasks.begin(); i != tasks.end(); i++) {
+                t = *i;
+                if ((t->getStatus() == Task::STOPPED) || (t->getStatus() == Task::FAULTED)) {
+                    delete t;
+                    tasks.erase(i);
+                    didDelete = true;
+                    break;
+                }
+            }
+        } while (didDelete);
+    } while (!stopped && tasks.size() != 0);
+}
+
+void Balau::TaskMan::registerTask(Balau::Task * t) {
+    // lock pending
+    pendingAdd.insert(t);
+    // unlock pending
 }
-- 
cgit v1.2.3