summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile24
-rw-r--r--includes/Local.h21
-rw-r--r--includes/Task.h38
-rw-r--r--includes/TaskMan.h21
m---------libcoro0
-rw-r--r--src/Local.cc4
-rw-r--r--src/Printer.cc29
-rw-r--r--src/Task.cc46
-rw-r--r--src/TaskMan.cc21
-rw-r--r--tests/test-Tasks.cc13
11 files changed, 192 insertions, 28 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..55cf452
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "libcoro"]
+ path = libcoro
+ url = git.grumpycoder.net:/pub/repo.git/libcoro
diff --git a/Makefile b/Makefile
index 58c41bf..79ed4c7 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,7 @@ AR = ar rcs
CPPFLAGS = -O3
ifeq ($(SYSTEM),Darwin)
+ LIBCORO_CFLAGS = -DCORO_SJLJ
ARCH_FLAGS = -arch i386
LIBS = -liconv
LD = g++ -arch i386
@@ -27,6 +28,7 @@ ifeq ($(SYSTEM),Darwin)
AS = i686-apple-darwin-as -arch i386
endif
else
+ LIBCORO_CFLAGS = -DCORO_ASM
ARCH_FLAGS = -march=i686 -m32
ASFLAGS = -march=i686 --32
STRIP = strip --strip-unneeded
@@ -34,30 +36,38 @@ else
LDFLAGS += -flto -O3
endif
-INCLUDES = -Iincludes
+INCLUDES = -Iincludes -Ilibcoro
-CPPFLAGS_NO_ARCH += $(INCLUDES) -g -DSTDC_HEADERS -fexceptions -DWORDS_LITTLEENDIAN $(HAVES)
+CPPFLAGS_NO_ARCH += $(INCLUDES) -g -DSTDC_HEADERS -fexceptions -DWORDS_LITTLEENDIAN $(HAVES) $(LIBCORO_CFLAGS)
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
LDFLAGS += $(ARCH_FLAGS) $(LIBS)
vpath %.cc src:tests
+vpath %.c libcoro
BALAU_SOURCES = \
BString.cc \
Local.cc \
Main.cc \
Printer.cc \
+Task.cc \
+TaskMan.cc \
+
+LIBCORO_SOURCES = \
+coro.c \
TEST_SOURCES = \
test-String.cc \
+test-Tasks.cc \
LIB = libBalau.a
-WHOLE_SOURCES = $(BALAU_SOURCES) $(TEST_SOURCES)
+BALAU_OBJECTS = $(addsuffix .o, $(notdir $(basename $(BALAU_SOURCES) $(LIBCORO_SOURCES))))
+
+WHOLE_SOURCES = $(BALAU_SOURCES) $(LIBCORO_SOURCES) $(TEST_SOURCES)
TESTS = $(notdir $(basename $(TEST_SOURCES)))
-BALAU_OBJECTS = $(addsuffix .o, $(notdir $(basename $(BALAU_SOURCES))))
ALL_OBJECTS = $(addsuffix .o, $(notdir $(basename $(WHOLE_SOURCES))))
ALL_DEPS = $(addsuffix .dep, $(notdir $(basename $(WHOLE_SOURCES))))
@@ -77,11 +87,17 @@ libBalau.a: $(BALAU_OBJECTS)
test-String: test-String.o $(LIB)
$(LD) $(LDFLAGS) -o $@ $< ./$(LIB)
+test-Tasks: test-Tasks.o $(LIB)
+ $(LD) $(LDFLAGS) -o $@ $< ./$(LIB)
+
dep: $(ALL_DEPS)
%.dep : %.cc
$(CXX) $(CPPFLAGS_NO_ARCH) -M -MF $@ $<
+%.dep : %.c
+ $(CC) $(CPPFLAGS_NO_ARCH) -M -MF $@ $<
+
-include $(ALL_DEPS)
clean:
diff --git a/includes/Local.h b/includes/Local.h
index f3b7250..a3405ca 100644
--- a/includes/Local.h
+++ b/includes/Local.h
@@ -8,6 +8,7 @@ class TLSManager {
public:
virtual void * getTLS();
virtual void * setTLS(void * val);
+ void * createTLS();
};
extern TLSManager * tlsManager;
@@ -32,6 +33,26 @@ class Local : public AtStart {
int m_idx;
static int s_size;
static void ** m_globals;
+
+ friend class TLSManager;
+};
+
+template<class T>
+class DefaultTmpl : public AtStart {
+ public:
+ DefaultTmpl(int pri) : AtStart(pri) { }
+ protected:
+ virtual void doStart() { new T; }
+};
+
+template<class T>
+class LocalTmpl : public Local {
+ public:
+ LocalTmpl() { }
+ T * getGlobal() { return reinterpret_cast<T *>(Local::getGlobal()); }
+ T * get() { return reinterpret_cast<T *>(Local::get()); }
+ void setGlobal(T * obj) { Local::setGlobal(obj); }
+ void set(T * obj) { Local::set(obj); }
};
};
diff --git a/includes/Task.h b/includes/Task.h
new file mode 100644
index 0000000..314532b
--- /dev/null
+++ b/includes/Task.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <stdlib.h>
+#include <coro.h>
+
+namespace Balau {
+
+class TaskMan;
+
+class Task {
+ public:
+ enum Status {
+ STARTING,
+ RUNNING,
+ IDLE,
+ STOPPED,
+ FAULTED,
+ };
+ Task();
+ ~Task() { free(stack); free(tls); }
+ virtual void Do() = 0;
+ virtual const char * getName() = 0;
+ Status getStatus() { return status; }
+ protected:
+ void suspend();
+ private:
+ size_t stackSize() { return 128 * 1024; }
+ void switchTo();
+ static void coroutine(void *);
+ void * stack;
+ coro_context ctx;
+ TaskMan * taskMan;
+ Status status;
+ void * tls;
+ friend class TaskMan;
+};
+
+};
diff --git a/includes/TaskMan.h b/includes/TaskMan.h
new file mode 100644
index 0000000..05e5fa8
--- /dev/null
+++ b/includes/TaskMan.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <coro.h>
+
+namespace Balau {
+
+class Task;
+
+class TaskMan {
+ public:
+ TaskMan();
+ ~TaskMan();
+ void mainLoop();
+
+ private:
+ static TaskMan * getTaskMan();
+ coro_context returnContext;
+ friend class Task;
+};
+
+};
diff --git a/libcoro b/libcoro
new file mode 160000
+Subproject 128d4e8c4a9103fe5a02682de89c6a660ff2a5d
diff --git a/src/Local.cc b/src/Local.cc
index 1262179..c354db9 100644
--- a/src/Local.cc
+++ b/src/Local.cc
@@ -13,6 +13,10 @@ void * Balau::TLSManager::setTLS(void * val) {
return r;
}
+void * Balau::TLSManager::createTLS() {
+ return Local::create();
+}
+
static Balau::TLSManager dummyTLSManager;
Balau::TLSManager * Balau::tlsManager = &dummyTLSManager;
diff --git a/src/Printer.cc b/src/Printer.cc
index fda9952..cb94084 100644
--- a/src/Printer.cc
+++ b/src/Printer.cc
@@ -2,14 +2,8 @@
#include "Main.h"
#include "Local.h"
-class PrinterLocal : public Balau::Local {
- public:
- PrinterLocal() { }
- Balau::Printer * getGlobal() { return reinterpret_cast<Balau::Printer *>(Local::getGlobal()); }
- Balau::Printer * get() { return reinterpret_cast<Balau::Printer *>(Local::get()); }
- void setGlobal(Balau::Printer * printer) { Local::setGlobal(printer); }
- void set(Balau::Printer * printer) { Local::set(printer); }
-} printerLocal;
+static Balau::DefaultTmpl<Balau::Printer> defaultPrinter(10);
+static Balau::LocalTmpl<Balau::Printer> localPrinter;
static const char * prefixes[] = {
"(DD) ",
@@ -21,11 +15,11 @@ static const char * prefixes[] = {
};
Balau::Printer::Printer() : m_verbosity(M_STATUS | M_WARNING | M_ERROR) {
- if (!printerLocal.getGlobal())
- printerLocal.setGlobal(this);
+ if (!localPrinter.getGlobal())
+ localPrinter.setGlobal(this);
}
-Balau::Printer * Balau::Printer::getPrinter() { return printerLocal.get(); }
+Balau::Printer * Balau::Printer::getPrinter() { return localPrinter.get(); }
void Balau::Printer::_log(uint32_t level, const char * fmt, va_list ap) {
if (!(level & m_verbosity))
@@ -45,16 +39,3 @@ void Balau::Printer::_log(uint32_t level, const char * fmt, va_list ap) {
void Balau::Printer::_print(const char * fmt, va_list ap) {
vfprintf(stderr, fmt, ap);
}
-
-class DefaultPrinter : public Balau::AtStart {
- public:
- DefaultPrinter() : AtStart(10) { }
- protected:
- virtual void doStart();
-};
-
-static DefaultPrinter defaultPrinter;
-
-void DefaultPrinter::doStart() {
- new Balau::Printer();
-}
diff --git a/src/Task.cc b/src/Task.cc
new file mode 100644
index 0000000..d41f088
--- /dev/null
+++ b/src/Task.cc
@@ -0,0 +1,46 @@
+#include "Task.h"
+#include "TaskMan.h"
+#include "Exceptions.h"
+#include "Printer.h"
+#include "Local.h"
+
+Balau::Task::Task() {
+ size_t size = stackSize();
+ stack = malloc(size);
+ coro_create(&ctx, coroutine, this, stack, size);
+ taskMan = TaskMan::getTaskMan();
+ tls = tlsManager->createTLS();
+ status = STARTING;
+}
+
+void Balau::Task::coroutine(void * arg) {
+ Task * task = reinterpret_cast<Task *>(arg);
+ Assert(task);
+ try {
+ task->status = RUNNING;
+ task->Do();
+ task->status = STOPPED;
+ }
+ catch (GeneralException & e) {
+ Printer::log(M_WARNING, "Task %s caused an exception: `%s' - stopping.", task->getName(), e.getMsg());
+ task->status = FAULTED;
+ }
+ catch (...) {
+ Printer::log(M_WARNING, "Task %s caused an unknown exception - stopping.", task->getName());
+ task->status = FAULTED;
+ }
+ coro_transfer(&task->ctx, &task->taskMan->returnContext);
+}
+
+void Balau::Task::switchTo() {
+ status = RUNNING;
+ void * oldTLS = tlsManager->getTLS();
+ tlsManager->setTLS(tls);
+ coro_transfer(&taskMan->returnContext, &ctx);
+ tlsManager->setTLS(oldTLS);
+ status = IDLE;
+}
+
+void Balau::Task::suspend() {
+ coro_transfer(&ctx, &taskMan->returnContext);
+}
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
new file mode 100644
index 0000000..783c683
--- /dev/null
+++ b/src/TaskMan.cc
@@ -0,0 +1,21 @@
+#include "TaskMan.h"
+#include "Main.h"
+#include "Local.h"
+
+static Balau::DefaultTmpl<Balau::TaskMan> defaultTaskMan(50);
+static Balau::LocalTmpl<Balau::TaskMan> localTaskMan;
+
+Balau::TaskMan::TaskMan() {
+ coro_create(&returnContext, 0, 0, 0, 0);
+ if (!localTaskMan.getGlobal())
+ localTaskMan.setGlobal(this);
+}
+
+Balau::TaskMan * Balau::TaskMan::getTaskMan() { return localTaskMan.get(); }
+
+Balau::TaskMan::~TaskMan() {
+ Assert(localTaskMan.getGlobal() != this);
+}
+
+void Balau::TaskMan::mainLoop() {
+}
diff --git a/tests/test-Tasks.cc b/tests/test-Tasks.cc
new file mode 100644
index 0000000..bb7c795
--- /dev/null
+++ b/tests/test-Tasks.cc
@@ -0,0 +1,13 @@
+#include <Main.h>
+#include <Task.h>
+#include <TaskMan.h>
+
+BALAU_STARTUP;
+
+using namespace Balau;
+
+int Application::startup() throw (Balau::GeneralException) {
+ Printer::log(M_STATUS, "Test::Tasks running.");
+ Printer::log(M_STATUS, "Test::Tasks passed.");
+ return 0;
+}