diff options
author | Pixel <pixel@nobis-crew.org> | 2011-10-18 16:37:49 -0700 |
---|---|---|
committer | Pixel <pixel@nobis-crew.org> | 2011-10-18 16:37:49 -0700 |
commit | 0db120afdfb818421dc5df3dc0946fafede78c93 (patch) | |
tree | e47403f57bcc39471d6c994c4f2951f4eb9ba108 | |
parent | 4e07ceeb21dae4b6b8d5eaf7421228f735f14bda (diff) |
libcoro seems to be doing really spurious things when not using the standard functions.
Switching out libcoro for the native Fibers interface for Win32.
Switching out the asm version for the ucontext version for Linux.
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | includes/Task.h | 12 | ||||
-rw-r--r-- | includes/TaskMan.h | 6 | ||||
-rw-r--r-- | linux-config.h | 2 | ||||
-rw-r--r-- | src/Task.cc | 20 | ||||
-rw-r--r-- | src/TaskMan.cc | 5 |
6 files changed, 45 insertions, 3 deletions
@@ -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); |