summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-10-09 01:12:50 -0700
committerPixel <pixel@nobis-crew.org>2011-10-09 01:12:50 -0700
commit864eeb3a526b1a32c72e1f31a3e1f23dcc5c7409 (patch)
tree7cc7037e2d7137180a67fb10b29469d4d68e677f /src
parent4f7b984f9f848ba6adae2040c520a97bb5c0e354 (diff)
More work on the Task manager.
Now "Main" is a Task, among the most important changes. Introduced the notion of Events, and managed a coherent task switch. Also, renamed a lot of the variables to have a more coherent naming scheme.
Diffstat (limited to 'src')
-rw-r--r--src/Local.cc2
-rw-r--r--src/Main.cc2
-rw-r--r--src/Task.cc64
-rw-r--r--src/TaskMan.cc62
4 files changed, 86 insertions, 44 deletions
diff --git a/src/Local.cc b/src/Local.cc
index c354db9..1619557 100644
--- a/src/Local.cc
+++ b/src/Local.cc
@@ -18,7 +18,7 @@ void * Balau::TLSManager::createTLS() {
}
static Balau::TLSManager dummyTLSManager;
-Balau::TLSManager * Balau::tlsManager = &dummyTLSManager;
+Balau::TLSManager * Balau::g_tlsManager = &dummyTLSManager;
int Balau::Local::s_size = 0;
void ** Balau::Local::m_globals = 0;
diff --git a/src/Main.cc b/src/Main.cc
index 04d867f..eb5e589 100644
--- a/src/Main.cc
+++ b/src/Main.cc
@@ -31,4 +31,4 @@ Balau::AtExit::AtExit(int priority) : m_priority(priority) {
*ptr = this;
}
-Balau::Main * Balau::Main::application = NULL;
+Balau::Main * Balau::Main::s_application = NULL;
diff --git a/src/Task.cc b/src/Task.cc
index 9bdad0c..73a2329 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -4,50 +4,72 @@
#include "Printer.h"
#include "Local.h"
+static Balau::LocalTmpl<Balau::Task> localTask;
+
Balau::Task::Task() {
size_t size = stackSize();
- stack = malloc(size);
- coro_create(&ctx, coroutine, this, stack, size);
- taskMan = TaskMan::getTaskMan();
- taskMan->registerTask(this);
- tls = tlsManager->createTLS();
- status = STARTING;
+ m_stack = malloc(size);
+ coro_create(&m_ctx, coroutine, this, m_stack, size);
+
+ m_taskMan = TaskMan::getTaskMan();
+ m_taskMan->registerTask(this);
+
+ m_tls = g_tlsManager->createTLS();
+ void * oldTLS = g_tlsManager->getTLS();
+ g_tlsManager->setTLS(m_tls);
+ localTask.set(this);
+ g_tlsManager->setTLS(oldTLS);
+
+ m_status = STARTING;
}
Balau::Task::~Task() {
- free(stack);
- free(tls);
+ free(m_stack);
+ free(m_tls);
}
void Balau::Task::coroutine(void * arg) {
Task * task = reinterpret_cast<Task *>(arg);
Assert(task);
try {
- task->status = RUNNING;
+ task->m_status = RUNNING;
task->Do();
- task->status = STOPPED;
+ task->m_status = STOPPED;
}
catch (GeneralException & e) {
Printer::log(M_WARNING, "Task %s caused an exception: `%s' - stopping.", task->getName(), e.getMsg());
- task->status = FAULTED;
+ task->m_status = FAULTED;
}
catch (...) {
Printer::log(M_WARNING, "Task %s caused an unknown exception - stopping.", task->getName());
- task->status = FAULTED;
+ task->m_status = FAULTED;
}
- coro_transfer(&task->ctx, &task->taskMan->returnContext);
+ coro_transfer(&task->m_ctx, &task->m_taskMan->m_returnContext);
}
void Balau::Task::switchTo() {
- status = RUNNING;
- void * oldTLS = tlsManager->getTLS();
- tlsManager->setTLS(tls);
- coro_transfer(&taskMan->returnContext, &ctx);
- tlsManager->setTLS(oldTLS);
- if (status == RUNNING)
- status = IDLE;
+ m_status = RUNNING;
+ void * oldTLS = g_tlsManager->getTLS();
+ g_tlsManager->setTLS(m_tls);
+ coro_transfer(&m_taskMan->m_returnContext, &m_ctx);
+ g_tlsManager->setTLS(oldTLS);
+ if (m_status == RUNNING)
+ m_status = IDLE;
}
void Balau::Task::suspend() {
- coro_transfer(&ctx, &taskMan->returnContext);
+ coro_transfer(&m_ctx, &m_taskMan->m_returnContext);
+}
+
+Balau::Task * Balau::Task::getCurrentTask() {
+ return localTask.get();
+}
+
+void Balau::Task::waitFor(Balau::Events::BaseEvent * e) {
+ e->registerOwner(this);
+ // probably have to register the event in the Task manager
+}
+
+Balau::Events::TaskEvent::TaskEvent(Task * taskWaited) : m_taskWaited(taskWaited) {
+ m_taskWaited->m_waitedBy.push_back(this);
}
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
index bbaf35c..6730f13 100644
--- a/src/TaskMan.cc
+++ b/src/TaskMan.cc
@@ -6,8 +6,8 @@
static Balau::DefaultTmpl<Balau::TaskMan> defaultTaskMan(50);
static Balau::LocalTmpl<Balau::TaskMan> localTaskMan;
-Balau::TaskMan::TaskMan() : stopped(false) {
- coro_create(&returnContext, 0, 0, 0, 0);
+Balau::TaskMan::TaskMan() : m_stopped(false) {
+ coro_create(&m_returnContext, 0, 0, 0, 0);
if (!localTaskMan.getGlobal())
localTaskMan.setGlobal(this);
}
@@ -21,21 +21,13 @@ Balau::TaskMan::~TaskMan() {
void Balau::TaskMan::mainLoop() {
// We need at least one round before bailing :)
do {
- taskList::iterator i;
+ taskList_t::iterator iL;
+ taskHash_t::iterator iH;
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;
+ for (iH = m_tasks.begin(); iH != m_tasks.end(); iH++) {
+ t = *iH;
if (t->getStatus() == Task::STARTING) {
t->switchTo();
}
@@ -43,25 +35,53 @@ void Balau::TaskMan::mainLoop() {
// That's probably where we poll for events
- // checking "STOPPED" tasks, and destroying them
+ // lock pending
+ // Adding tasks that were added, maybe from other threads
+ for (iL = m_pendingAdd.begin(); iL != m_pendingAdd.end(); iL++) {
+ t = *iL;
+ Assert(m_tasks.find(t) == m_tasks.end());
+ m_tasks.insert(t);
+ }
+ m_pendingAdd.clear();
+ // unlock pending
+
+ // Dealing with stopped and faulted tasks.
+ // First by signalling the waiters.
+ for (iH = m_tasks.begin(); iH != m_tasks.end(); iH++) {
+ t = *iH;
+ if (((t->getStatus() == Task::STOPPED) || (t->getStatus() == Task::FAULTED)) &&
+ (t->m_waitedBy.size() != 0)) {
+ Task::waitedByList_t::iterator i;
+ while ((i = t->m_waitedBy.begin()) != t->m_waitedBy.end()) {
+ Events::TaskEvent * e = *i;
+ e->doSignal();
+ e->taskWaiting()->switchTo();
+ t->m_waitedBy.erase(i);
+ }
+ }
+ }
+
+ // Then, by 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)) {
+ for (iH = m_tasks.begin(); iH != m_tasks.end(); iH++) {
+ t = *iH;
+ if (((t->getStatus() == Task::STOPPED) || (t->getStatus() == Task::FAULTED)) &&
+ (t->m_waitedBy.size() == 0)) {
delete t;
- tasks.erase(i);
+ m_tasks.erase(iH);
didDelete = true;
break;
}
}
} while (didDelete);
- } while (!stopped && tasks.size() != 0);
+
+ } while (!m_stopped && m_tasks.size() != 0);
}
void Balau::TaskMan::registerTask(Balau::Task * t) {
// lock pending
- pendingAdd.insert(t);
+ m_pendingAdd.push_back(t);
// unlock pending
}