summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--includes/Task.h12
-rw-r--r--includes/TaskMan.h6
-rw-r--r--linux-config.h2
-rw-r--r--src/Task.cc20
-rw-r--r--src/TaskMan.cc5
6 files changed, 45 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 051d84c..85dbab5 100644
--- a/Makefile
+++ b/Makefile
@@ -139,9 +139,12 @@ darwin-eprintf.c \
endif
+ifneq ($(SYSTEM),MINGW32)
LIBCORO_SOURCES = \
coro.c \
+endif
+
LIBEV_SOURCES = \
ev.c \
event.c \
diff --git a/includes/Task.h b/includes/Task.h
index 042624d..b124731 100644
--- a/includes/Task.h
+++ b/includes/Task.h
@@ -1,7 +1,9 @@
#pragma once
#include <stdlib.h>
+#ifndef _WIN32
#include <coro.h>
+#endif
#include <ev++.h>
#include <vector>
#include <Exceptions.h>
@@ -81,6 +83,10 @@ class Async : public BaseEvent {
ev::async m_evt;
};
+#ifndef _WIN32
+#define CALLBACK
+#endif
+
class Custom : public BaseEvent {
public:
void doSignal() { BaseEvent::doSignal(); ev_break(m_loop, EVBREAK_ALL); }
@@ -137,9 +143,13 @@ class Task {
private:
size_t stackSize() { return 128 * 1024; }
void switchTo();
- static void coroutine(void *);
+ static void CALLBACK coroutine(void *);
void * m_stack;
+#ifndef _WIN32
coro_context m_ctx;
+#else
+ void * m_fiber;
+#endif
TaskMan * m_taskMan;
Status m_status;
void * m_tls;
diff --git a/includes/TaskMan.h b/includes/TaskMan.h
index 8144e93..ad19f65 100644
--- a/includes/TaskMan.h
+++ b/includes/TaskMan.h
@@ -1,7 +1,9 @@
#pragma once
#include <stdint.h>
+#ifndef _WIN32
#include <coro.h>
+#endif
#include <ev++.h>
#include <ext/hash_set>
#include <vector>
@@ -26,7 +28,11 @@ class TaskMan {
private:
void registerTask(Task * t);
void unregisterTask(Task * t);
+#ifndef _WIN32
coro_context m_returnContext;
+#else
+ void * m_fiber;
+#endif
friend class Task;
struct taskHasher { size_t operator()(const Task * t) const { return reinterpret_cast<uintptr_t>(t); } };
typedef gnu::hash_set<Task *, taskHasher> taskHash_t;
diff --git a/linux-config.h b/linux-config.h
index 4531a67..fe447b7 100644
--- a/linux-config.h
+++ b/linux-config.h
@@ -2,7 +2,7 @@
#define STDC_HEADERS 1
#define WORDS_LITTLEENDIAN 1
-#define CORO_ASM 1
+#define CORO_UCONTEXT 1
#define _FILE_OFFSET_BITS 64
#define EMBED_LIBEIO 1
diff --git a/src/Task.cc b/src/Task.cc
index 558b7de..ad481cc 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -8,8 +8,13 @@ static Balau::LocalTmpl<Balau::Task> localTask;
Balau::Task::Task() {
size_t size = stackSize();
+#ifndef _WIN32
m_stack = malloc(size);
coro_create(&m_ctx, coroutine, this, m_stack, size);
+#else
+ m_stack = NULL;
+ m_fiber = CreateFiber(size, coroutine, this);
+#endif
m_taskMan = TaskMan::getTaskMan();
m_taskMan->registerTask(this);
@@ -27,7 +32,8 @@ Balau::Task::Task() {
}
Balau::Task::~Task() {
- free(m_stack);
+ if (m_stack)
+ free(m_stack);
free(m_tls);
}
@@ -48,7 +54,11 @@ void Balau::Task::coroutine(void * arg) {
Printer::log(M_WARNING, "Task %s at %p caused an unknown exception - stopping.", task->getName(), task);
task->m_status = FAULTED;
}
+#ifndef _WIN32
coro_transfer(&task->m_ctx, &task->m_taskMan->m_returnContext);
+#else
+ SwitchToFiber(task->m_taskMan->m_fiber);
+#endif
}
void Balau::Task::switchTo() {
@@ -56,7 +66,11 @@ void Balau::Task::switchTo() {
Assert(m_status == IDLE || m_status == STARTING);
void * oldTLS = g_tlsManager->getTLS();
g_tlsManager->setTLS(m_tls);
+#ifndef _WIN32
coro_transfer(&m_taskMan->m_returnContext, &m_ctx);
+#else
+ SwitchToFiber(m_fiber);
+#endif
g_tlsManager->setTLS(oldTLS);
if (m_status == RUNNING)
m_status = IDLE;
@@ -64,7 +78,11 @@ void Balau::Task::switchTo() {
void Balau::Task::yield() {
Printer::elog(E_TASK, "Task %p - %s yielding", this, getName());
+#ifndef _WIN32
coro_transfer(&m_ctx, &m_taskMan->m_returnContext);
+#else
+ SwitchToFiber(m_taskMan->m_fiber);
+#endif
}
Balau::Task * Balau::Task::getCurrentTask() {
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
index fc33530..0fc4668 100644
--- a/src/TaskMan.cc
+++ b/src/TaskMan.cc
@@ -7,7 +7,12 @@ static Balau::DefaultTmpl<Balau::TaskMan> defaultTaskMan(50);
static Balau::LocalTmpl<Balau::TaskMan> localTaskMan;
Balau::TaskMan::TaskMan() : m_stopped(false), m_allowedToSignal(false) {
+#ifndef _WIN32
coro_create(&m_returnContext, 0, 0, 0, 0);
+#else
+ m_fiber = ConvertThreadToFiber(NULL);
+ Assert(m_fiber);
+#endif
if (!localTaskMan.getGlobal()) {
localTaskMan.setGlobal(this);
m_loop = ev_default_loop(EVFLAG_AUTO);