summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-08-02 10:04:38 +0200
committerNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-08-02 10:22:15 +0200
commit6d956657c4612e988f89a133cea93e50ec2dcb39 (patch)
treee5f360dd667145934141549fad1866e61b87e5bf
parent7f4f068ebdfd51c358648e514660b23d586d4929 (diff)
Adding AtStartAsTask and AtExitAsTask concepts.
-rw-r--r--includes/AtStartExit.h29
-rw-r--r--src/Main.cc97
2 files changed, 125 insertions, 1 deletions
diff --git a/includes/AtStartExit.h b/includes/AtStartExit.h
index 97dc533..4cd49a5 100644
--- a/includes/AtStartExit.h
+++ b/includes/AtStartExit.h
@@ -2,6 +2,9 @@
namespace Balau {
+class Task;
+class BootstrapTask;
+
class AtStart {
protected:
AtStart(int priority = 0);
@@ -28,4 +31,30 @@ class AtExit {
friend class Main;
};
+class AtStartAsTask {
+ protected:
+ AtStartAsTask(int priority = 0);
+ virtual Task * createStartTask() = 0;
+ private:
+ AtStartAsTask(const AtStartAsTask &) = delete;
+ AtStart & operator=(const AtStartAsTask &) = delete;
+ const int m_priority;
+ AtStartAsTask * m_next;
+ static AtStartAsTask * s_head;
+ friend class BootstrapTask;
+};
+
+class AtExitAsTask {
+ protected:
+ AtExitAsTask(int priority = 0);
+ virtual Task * createExitTask() = 0;
+ private:
+ AtExitAsTask(const AtExit &) = delete;
+ AtExitAsTask & operator=(const AtExitAsTask &) = delete;
+ const int m_priority;
+ AtExitAsTask * m_next;
+ static AtExitAsTask * s_head;
+ friend class BootstrapTask;
+};
+
};
diff --git a/src/Main.cc b/src/Main.cc
index 7c205d4..e872411 100644
--- a/src/Main.cc
+++ b/src/Main.cc
@@ -2,9 +2,12 @@
#include "TaskMan.h"
#include "Printer.h"
#include "AtStartExit.h"
+#include "StacklessTask.h"
Balau::AtStart * Balau::AtStart::s_head = 0;
Balau::AtExit * Balau::AtExit::s_head = 0;
+Balau::AtStartAsTask * Balau::AtStartAsTask::s_head = 0;
+Balau::AtExitAsTask * Balau::AtExitAsTask::s_head = 0;
Balau::AtStart::AtStart(int priority) : m_priority(priority) {
if (priority < 0)
@@ -36,6 +39,36 @@ Balau::AtExit::AtExit(int priority) : m_priority(priority) {
*ptr = this;
}
+Balau::AtStartAsTask::AtStartAsTask(int priority) : m_priority(priority) {
+ if (priority < 0)
+ return;
+ AAssert(!Main::hasMain(), "An AtStartAsTask can't be created dynamically");
+
+ AtStartAsTask ** ptr = &s_head;
+
+ m_next = 0;
+
+ for (ptr = &s_head; *ptr && (priority > (*ptr)->m_priority); ptr = &((*ptr)->m_next));
+
+ m_next = *ptr;
+ *ptr = this;
+}
+
+Balau::AtExitAsTask::AtExitAsTask(int priority) : m_priority(priority) {
+ if (priority < 0)
+ return;
+ AAssert(!Main::hasMain(), "An AtExitAsTask can't be created dynamically");
+
+ AtExitAsTask ** ptr = &s_head;
+
+ m_next = 0;
+
+ for (ptr = &s_head; *ptr && (priority > (*ptr)->m_priority); ptr = &((*ptr)->m_next));
+
+ m_next = *ptr;
+ *ptr = this;
+}
+
Balau::Main * Balau::Main::s_application = NULL;
Balau::MainTask::~MainTask() {
@@ -47,6 +80,68 @@ const char * Balau::MainTask::getName() const {
return "Main Task";
}
+namespace Balau {
+
+class BootstrapTask : public StacklessTask {
+ public:
+ BootstrapTask(int argc, char ** argv, char ** enve) : m_argc(argc), m_argv(argv), m_enve(enve) { }
+ virtual void Do() {
+ Balau::Task * t;
+ try {
+ switch (m_state) {
+ case 0:
+ m_ptrStart = AtStartAsTask::s_head;
+ m_ptrExit = AtExitAsTask::s_head;
+ m_state = 1;
+ case 1:
+ if (m_ptrStart) {
+ t = m_ptrStart->createStartTask();
+ if (m_waiting)
+ m_evt.ack();
+ m_evt.attachToTask(t);
+ m_waiting = true;
+ waitFor(&m_evt);
+ TaskMan::registerTask(t);
+ m_ptrStart = m_ptrStart->m_next;
+ yield();
+ }
+ m_state = 2;
+ t = new MainTask(m_argc, m_argv, m_enve);
+ if (m_waiting)
+ m_evt.ack();
+ m_evt.attachToTask(t);
+ waitFor(&m_evt);
+ TaskMan::registerTask(t);
+ yield();
+ case 2:
+ if (m_ptrExit) {
+ t = m_ptrExit->createExitTask();
+ m_evt.ack();
+ m_evt.attachToTask(t);
+ waitFor(&m_evt);
+ TaskMan::registerTask(t);
+ m_ptrExit = m_ptrExit->m_next;
+ yield();
+ }
+ }
+ }
+ catch (EAgain &) {
+ taskSwitch();
+ }
+ }
+ private:
+ virtual const char * getName() const { return "BootstrapTask"; }
+ int m_argc;
+ char ** m_argv;
+ char ** m_enve;
+ AtStartAsTask * m_ptrStart = NULL;
+ AtExitAsTask * m_ptrExit = NULL;
+ Events::TaskEvent m_evt;
+ bool m_waiting = false;
+};
+
+};
+
int Balau::Main::bootstrap(int argc, char ** argv) {
int r = 0;
m_status = STARTING;
@@ -56,7 +151,7 @@ int Balau::Main::bootstrap(int argc, char ** argv) {
try {
m_status = RUNNING;
- TaskMan::registerTask(new MainTask(argc, argv, NULL));
+ TaskMan::registerTask(new BootstrapTask(argc, argv, NULL));
r = TaskMan::getDefaultTaskMan()->mainLoop();
m_status = STOPPING;
}