summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/Task.h17
-rw-r--r--includes/TaskMan.h6
-rw-r--r--linux-config.h1
-rw-r--r--src/Task.cc20
-rw-r--r--src/TaskMan.cc23
-rw-r--r--tests/test-Tasks.cc14
6 files changed, 72 insertions, 9 deletions
diff --git a/includes/Task.h b/includes/Task.h
index c2777fe..f0c1bbb 100644
--- a/includes/Task.h
+++ b/includes/Task.h
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <coro.h>
+#include <ev++.h>
#include <Exceptions.h>
#include <vector>
@@ -16,14 +17,25 @@ class BaseEvent {
public:
BaseEvent() : m_signal(false), m_task(NULL) { }
bool gotSignal() { return m_signal; }
- void doSignal() { m_signal = true; }
+ void doSignal();
Task * taskWaiting() { Assert(m_task); return m_task; }
- void registerOwner(Task * task) { Assert(m_task == NULL); m_task = task; }
+ void registerOwner(Task * task) { Assert(m_task == NULL); m_task = task; gotOwner(task); }
+ protected:
+ virtual void gotOwner(Task * task) { }
private:
bool m_signal;
Task * m_task;
};
+class Timeout : public BaseEvent {
+ public:
+ Timeout(ev_tstamp tstamp);
+ void evt_cb(ev::timer & w, int revents);
+ private:
+ virtual void gotOwner(Task * task);
+ ev::timer m_evt;
+};
+
class TaskEvent : public BaseEvent {
public:
TaskEvent(Task * taskWaited);
@@ -48,6 +60,7 @@ class Task {
virtual const char * getName() = 0;
Status getStatus() { return m_status; }
static Task * getCurrentTask();
+ TaskMan * getTaskMan() { return m_taskMan; }
protected:
void suspend();
virtual void Do() = 0;
diff --git a/includes/TaskMan.h b/includes/TaskMan.h
index 585fb7f..d8d0c80 100644
--- a/includes/TaskMan.h
+++ b/includes/TaskMan.h
@@ -2,6 +2,7 @@
#include <stdint.h>
#include <coro.h>
+#include <ev++.h>
#include <ext/hash_set>
#include <vector>
@@ -18,6 +19,8 @@ class TaskMan {
void mainLoop();
void stop() { m_stopped = true; }
static TaskMan * getTaskMan();
+ struct ev_loop * getLoop() { return m_loop; }
+ void signalTask(Task * t);
private:
void registerTask(Task * t);
@@ -27,9 +30,10 @@ class TaskMan {
struct taskHasher { size_t operator()(const Task * t) const { return reinterpret_cast<uintptr_t>(t); } };
typedef gnu::hash_set<Task *, taskHasher> taskHash_t;
typedef std::vector<Task *> taskList_t;
- taskHash_t m_tasks;
+ taskHash_t m_tasks, m_signaledTasks;
taskList_t m_pendingAdd;
volatile bool m_stopped;
+ struct ev_loop * m_loop;
};
};
diff --git a/linux-config.h b/linux-config.h
index 10e8bee..cb3b1b1 100644
--- a/linux-config.h
+++ b/linux-config.h
@@ -26,6 +26,7 @@
#define HAVE_UTIMES 1
/* libev config */
+#define EV_STANDALONE 1
#define HAVE_CLOCK_SYSCALL 1
#define HAVE_EPOLL_CTL 1
#define HAVE_EVENTFD 1
diff --git a/src/Task.cc b/src/Task.cc
index 73a2329..e5c971d 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -67,9 +67,27 @@ Balau::Task * Balau::Task::getCurrentTask() {
void Balau::Task::waitFor(Balau::Events::BaseEvent * e) {
e->registerOwner(this);
- // probably have to register the event in the Task manager
+}
+
+void Balau::Events::BaseEvent::doSignal() {
+ m_signal = true;
+ m_task->getTaskMan()->signalTask(m_task);
}
Balau::Events::TaskEvent::TaskEvent(Task * taskWaited) : m_taskWaited(taskWaited) {
m_taskWaited->m_waitedBy.push_back(this);
}
+
+Balau::Events::Timeout::Timeout(ev_tstamp tstamp) {
+ m_evt.set<Timeout, &Timeout::evt_cb>(this);
+ m_evt.set(tstamp);
+}
+
+void Balau::Events::Timeout::gotOwner(Task * task) {
+ m_evt.set(task->getTaskMan()->getLoop());
+ m_evt.start();
+}
+
+void Balau::Events::Timeout::evt_cb(ev::timer & w, int revents) {
+ doSignal();
+}
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
index 6730f13..a9ad709 100644
--- a/src/TaskMan.cc
+++ b/src/TaskMan.cc
@@ -8,14 +8,19 @@ static Balau::LocalTmpl<Balau::TaskMan> localTaskMan;
Balau::TaskMan::TaskMan() : m_stopped(false) {
coro_create(&m_returnContext, 0, 0, 0, 0);
- if (!localTaskMan.getGlobal())
+ if (!localTaskMan.getGlobal()) {
localTaskMan.setGlobal(this);
+ m_loop = ev_default_loop(EVFLAG_AUTO);
+ } else {
+ m_loop = ev_loop_new(EVFLAG_AUTO);
+ }
}
Balau::TaskMan * Balau::TaskMan::getTaskMan() { return localTaskMan.get(); }
Balau::TaskMan::~TaskMan() {
Assert(localTaskMan.getGlobal() != this);
+ ev_loop_destroy(m_loop);
}
void Balau::TaskMan::mainLoop() {
@@ -33,8 +38,6 @@ void Balau::TaskMan::mainLoop() {
}
}
- // That's probably where we poll for events
-
// lock pending
// Adding tasks that were added, maybe from other threads
for (iL = m_pendingAdd.begin(); iL != m_pendingAdd.end(); iL++) {
@@ -45,6 +48,14 @@ void Balau::TaskMan::mainLoop() {
m_pendingAdd.clear();
// unlock pending
+ ev_run(m_loop, EVRUN_ONCE);
+
+ // let's check who got signaled, and call them
+ for (iH = m_signaledTasks.begin(); iH != m_signaledTasks.end(); iH++) {
+ t = *iH;
+ t->switchTo();
+ }
+
// Dealing with stopped and faulted tasks.
// First by signalling the waiters.
for (iH = m_tasks.begin(); iH != m_tasks.end(); iH++) {
@@ -60,6 +71,7 @@ void Balau::TaskMan::mainLoop() {
}
}
}
+ m_signaledTasks.clear();
// Then, by destroying them.
bool didDelete;
@@ -85,3 +97,8 @@ void Balau::TaskMan::registerTask(Balau::Task * t) {
m_pendingAdd.push_back(t);
// unlock pending
}
+
+void Balau::TaskMan::signalTask(Task * t) {
+ Assert(m_tasks.find(t) != m_tasks.end());
+ m_signaledTasks.insert(t);
+}
diff --git a/tests/test-Tasks.cc b/tests/test-Tasks.cc
index 8de9cf1..148f943 100644
--- a/tests/test-Tasks.cc
+++ b/tests/test-Tasks.cc
@@ -25,10 +25,20 @@ class TestTask : public Task {
void MainTask::Do() {
customPrinter = new CustomPrinter();
Printer::log(M_STATUS, "Test::Tasks running.");
+
Task * testTask = new TestTask();
- Events::TaskEvent e(testTask);
- waitFor(&e);
+ Events::TaskEvent taskEvt(testTask);
+ waitFor(&taskEvt);
+ Assert(!taskEvt.gotSignal());
+ suspend();
+ Assert(taskEvt.gotSignal());
+
+ Events::Timeout timeout(0.1);
+ waitFor(&timeout);
+ Assert(!timeout.gotSignal());
suspend();
+ Assert(timeout.gotSignal());
+
Printer::log(M_STATUS, "Test::Tasks passed.");
Printer::log(M_DEBUG, "You shouldn't see that message.");
}