From 883dee678eca4f55faf3848a248253d4b4b8a40e Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 22 Mar 2010 12:32:11 +0100 Subject: Rename Fiber -> Coroutine. * Avoid confusion with Windows fibers. * Easier to search for. --- coroutine.pro | 2 + fibers.pro | 2 - src/coroutine.cpp | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/coroutine.h | 43 ++++++++++++++++++ src/fiber.cpp | 127 ------------------------------------------------------ src/fiber.h | 43 ------------------ src/src.pro | 6 +-- 7 files changed, 175 insertions(+), 175 deletions(-) create mode 100644 coroutine.pro delete mode 100644 fibers.pro create mode 100644 src/coroutine.cpp create mode 100644 src/coroutine.h delete mode 100644 src/fiber.cpp delete mode 100644 src/fiber.h diff --git a/coroutine.pro b/coroutine.pro new file mode 100644 index 0000000..65d9262 --- /dev/null +++ b/coroutine.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = src diff --git a/fibers.pro b/fibers.pro deleted file mode 100644 index 65d9262..0000000 --- a/fibers.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = src diff --git a/src/coroutine.cpp b/src/coroutine.cpp new file mode 100644 index 0000000..eb6ebc5 --- /dev/null +++ b/src/coroutine.cpp @@ -0,0 +1,127 @@ +#include +#include +#include + +#include "coroutine.h" + +/*! + \class Coroutine + \brief The Coroutine class provides cooperatively scheduled stacks of execution. + + Coroutines, also known as fibers, allow managing multiple stacks in the same + thread. + + \omit ### outdated \endomit + To create a coroutine, subclass Coroutine and override the run() method. To run it, + call cont(). This will execute the code in run() until it calls Coroutine::yield(). + At that point, the call to cont() returns. Subsequent calls to cont() will + continue execution of the coroutine just after the yield(). + + Example: + void myCoroutine() + { + qDebug() << "1"; + Coroutine::yield(); + qDebug() << "2"; + } + + MyCoroutine c(&myCoroutine); + qDebug() << "0.5"; + c.cont(); // prints 1 + qDebug() << "1.5"; + c.cont(); // prints 2 +*/ + +#ifdef Q_OS_MAC +extern "C" void switchStackInternal(void* to, void** from); +void initializeStack(void *data, int size, void (*entry)(), void **stackPointer); +void switchStack(void* to, void** from) { switchStackInternal(to, from); } +#else +extern "C" void _switchStackInternal(void* to, void** from); +void initializeStack(void *data, int size, void (*entry)(), void **stackPointer); +void switchStack(void* to, void** from) { _switchStackInternal(to, from); } +#endif + +Coroutine::Coroutine(StartFunction startFunction, int stackSize) + : _startFunction(startFunction) + , _stackData(0) + , _stackPointer(0) + , _previousCoroutine(0) + , _status(NotStarted) +{ + // establish starting coroutine context if necessary + currentCoroutine(); + + _stackData = malloc(stackSize); + initializeStack(_stackData, stackSize, &entryPoint, &_stackPointer); +} + +Coroutine::Coroutine() + : _startFunction(0) + , _stackData(0) + , _stackPointer(0) + , _previousCoroutine(0) + , _status(Running) +{ +} + +Coroutine::~Coroutine() +{ + if (_stackData) + free(_stackData); +} + +static QThreadStorage qt_currentCoroutine; + +Coroutine *Coroutine::currentCoroutine() +{ + Coroutine *current = qt_currentCoroutine.localData(); + if (current) + return current; + + // establish a context for the starting coroutine + current = new Coroutine; + qt_currentCoroutine.setLocalData(current); + return current; +} + +void Coroutine::entryPoint() +{ + qt_currentCoroutine.localData()->_startFunction(); + yieldHelper(Terminated); + Q_ASSERT(0); // unreachable +} + +// returns whether it can be continued again +bool Coroutine::cont() +{ + Q_ASSERT(_status == NotStarted || _status == Stopped); + Q_ASSERT(!_previousCoroutine); + + _status = Running; + + _previousCoroutine = qt_currentCoroutine.localData(); + qt_currentCoroutine.setLocalData(this); + switchStack(_stackPointer, &_previousCoroutine->_stackPointer); + return _status != Terminated; +} + +void Coroutine::yield() +{ + yieldHelper(Stopped); +} + +void Coroutine::yieldHelper(Status stopStatus) +{ + Coroutine *stoppingCoroutine = qt_currentCoroutine.localData(); + Q_ASSERT(stoppingCoroutine); + Q_ASSERT(stoppingCoroutine->_status == Running); + stoppingCoroutine->_status = stopStatus; + + Coroutine *continuingCoroutine = stoppingCoroutine->_previousCoroutine; + Q_ASSERT(continuingCoroutine); + + stoppingCoroutine->_previousCoroutine = 0; + qt_currentCoroutine.setLocalData(continuingCoroutine); + switchStack(continuingCoroutine, &stoppingCoroutine->_stackPointer); +} diff --git a/src/coroutine.h b/src/coroutine.h new file mode 100644 index 0000000..ca47e77 --- /dev/null +++ b/src/coroutine.h @@ -0,0 +1,43 @@ +#ifndef INCLUDE_COROUTINE_H +#define INCLUDE_COROUTINE_H + +class Coroutine +{ +public: + typedef void(*StartFunction)(); + + enum Status + { + NotStarted, + Running, + Stopped, + Terminated + }; + +public: + explicit Coroutine(StartFunction startFunction, int stackSize = 32768); + ~Coroutine(); + + bool cont(); + static void yield(); + + Status status() + { return _status; } + + static Coroutine *currentCoroutine(); + +private: + // for the original coroutine + Coroutine(); + + static void yieldHelper(Status stopStatus); + static void entryPoint(); + + StartFunction _startFunction; + void *_stackData; + void *_stackPointer; + Coroutine *_previousCoroutine; + Status _status; +}; + +#endif // INCLUDE_COROUTINE_H diff --git a/src/fiber.cpp b/src/fiber.cpp deleted file mode 100644 index 1c484e1..0000000 --- a/src/fiber.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include -#include -#include - -#include "fiber.h" - -/*! - \class Fiber - \brief The Fiber class provides cooperatively scheduled stacks of execution. - - Fibers, also known as coroutines, allow managing multiple stacks in the same - thread. - - \omit ### outdated \endomit - To create a fiber, subclass Fiber and override the run() method. To run it, - call cont(). This will execute the code in run() until it calls Fiber::yield(). - At that point, the call to cont() returns. Subsequent calls to cont() will - continue execution of the fiber just after the yield(). - - Example: - void myFiber() - { - qDebug() << "1"; - Fiber::yield(); - qDebug() << "2"; - } - - MyFiber fib(&myFiber); - qDebug() << "0.5"; - fib.cont(); // prints 1 - qDebug() << "1.5"; - fib.cont(); // prints 2 -*/ - -#ifdef Q_OS_MAC -extern "C" void switchStackInternal(void* to, void** from); -void initializeStack(void *data, int size, void (*entry)(), void **stackPointer); -void switchStack(void* to, void** from) { switchStackInternal(to, from); } -#else -extern "C" void _switchStackInternal(void* to, void** from); -void initializeStack(void *data, int size, void (*entry)(), void **stackPointer); -void switchStack(void* to, void** from) { _switchStackInternal(to, from); } -#endif - -Fiber::Fiber(StartFunction startFunction, int stackSize) - : _startFunction(startFunction) - , _stackData(0) - , _stackPointer(0) - , _previousFiber(0) - , _status(NotStarted) -{ - // establish starting fiber context if necessary - currentFiber(); - - _stackData = malloc(stackSize); - initializeStack(_stackData, stackSize, &entryPoint, &_stackPointer); -} - -Fiber::Fiber() - : _startFunction(0) - , _stackData(0) - , _stackPointer(0) - , _previousFiber(0) - , _status(Running) -{ -} - -Fiber::~Fiber() -{ - if (_stackData) - free(_stackData); -} - -static QThreadStorage qt_currentFiber; - -Fiber *Fiber::currentFiber() -{ - Fiber *current = qt_currentFiber.localData(); - if (current) - return current; - - // establish a context for the starting fiber - current = new Fiber; - qt_currentFiber.setLocalData(current); - return current; -} - -void Fiber::entryPoint() -{ - qt_currentFiber.localData()->_startFunction(); - yieldHelper(Terminated); - Q_ASSERT(0); // unreachable -} - -// returns whether it can be continued again -bool Fiber::cont() -{ - Q_ASSERT(_status == NotStarted || _status == Stopped); - Q_ASSERT(!_previousFiber); - - _status = Running; - - _previousFiber = qt_currentFiber.localData(); - qt_currentFiber.setLocalData(this); - switchStack(_stackPointer, &_previousFiber->_stackPointer); - return _status != Terminated; -} - -void Fiber::yield() -{ - yieldHelper(Stopped); -} - -void Fiber::yieldHelper(Status stopStatus) -{ - Fiber *stoppingFiber = qt_currentFiber.localData(); - Q_ASSERT(stoppingFiber); - Q_ASSERT(stoppingFiber->_status == Running); - stoppingFiber->_status = stopStatus; - - Fiber *continuingFiber = stoppingFiber->_previousFiber; - Q_ASSERT(continuingFiber); - - stoppingFiber->_previousFiber = 0; - qt_currentFiber.setLocalData(continuingFiber); - switchStack(continuingFiber, &stoppingFiber->_stackPointer); -} diff --git a/src/fiber.h b/src/fiber.h deleted file mode 100644 index b7bbcb1..0000000 --- a/src/fiber.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef INCLUDE_FIBER_H -#define INCLUDE_FIBER_H - -class Fiber -{ -public: - typedef void(*StartFunction)(); - - enum Status - { - NotStarted, - Running, - Stopped, - Terminated - }; - -public: - explicit Fiber(StartFunction startFunction, int stackSize = 32768); - ~Fiber(); - - bool cont(); - static void yield(); - - Status status() - { return _status; } - - static Fiber *currentFiber(); - -private: - // for the original fiber - Fiber(); - - static void yieldHelper(Status stopStatus); - static void entryPoint(); - - StartFunction _startFunction; - void *_stackData; - void *_stackPointer; - Fiber *_previousFiber; - Status _status; -}; - -#endif // INCLUDE_FIBER_H diff --git a/src/src.pro b/src/src.pro index b2b9f6d..6fe0bd2 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,8 +1,8 @@ TEMPLATE = lib -TARGET = fibers +TARGET = coroutine -HEADERS += fiber.h -SOURCES += fiber.cpp +HEADERS += coroutine.h +SOURCES += coroutine.cpp INCLUDEPATH += . DEPENDPATH += . -- cgit v1.2.3