diff options
| author | Christian Kamm <christian.d.kamm@nokia.com> | 2010-03-22 12:32:11 +0100 |
|---|---|---|
| committer | Christian Kamm <christian.d.kamm@nokia.com> | 2010-03-26 13:05:02 +0100 |
| commit | 883dee678eca4f55faf3848a248253d4b4b8a40e (patch) | |
| tree | f13c70472015d70cac2707a4dd5b8d295a437b5a | |
| parent | b03a4b990d9d26f62958cb1968bcf463e6d87eb5 (diff) | |
Rename Fiber -> Coroutine.
* Avoid confusion with Windows fibers.
* Easier to search for.
| -rw-r--r-- | coroutine.pro (renamed from fibers.pro) | 0 | ||||
| -rw-r--r-- | src/coroutine.cpp | 127 | ||||
| -rw-r--r-- | src/coroutine.h (renamed from src/fiber.h) | 20 | ||||
| -rw-r--r-- | src/fiber.cpp | 127 | ||||
| -rw-r--r-- | src/src.pro | 6 |
5 files changed, 140 insertions, 140 deletions
diff --git a/fibers.pro b/coroutine.pro index 65d9262..65d9262 100644 --- a/fibers.pro +++ b/coroutine.pro 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 <stdlib.h> +#include <QtCore/QtGlobal> +#include <QtCore/QThreadStorage> + +#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<Coroutine *> 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/fiber.h b/src/coroutine.h index b7bbcb1..ca47e77 100644 --- a/src/fiber.h +++ b/src/coroutine.h @@ -1,7 +1,7 @@ -#ifndef INCLUDE_FIBER_H -#define INCLUDE_FIBER_H +#ifndef INCLUDE_COROUTINE_H +#define INCLUDE_COROUTINE_H -class Fiber +class Coroutine { public: typedef void(*StartFunction)(); @@ -15,8 +15,8 @@ public: }; public: - explicit Fiber(StartFunction startFunction, int stackSize = 32768); - ~Fiber(); + explicit Coroutine(StartFunction startFunction, int stackSize = 32768); + ~Coroutine(); bool cont(); static void yield(); @@ -24,11 +24,11 @@ public: Status status() { return _status; } - static Fiber *currentFiber(); + static Coroutine *currentCoroutine(); private: - // for the original fiber - Fiber(); + // for the original coroutine + Coroutine(); static void yieldHelper(Status stopStatus); static void entryPoint(); @@ -36,8 +36,8 @@ private: StartFunction _startFunction; void *_stackData; void *_stackPointer; - Fiber *_previousFiber; + Coroutine *_previousCoroutine; Status _status; }; -#endif // INCLUDE_FIBER_H +#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 <stdlib.h> -#include <QtCore/QtGlobal> -#include <QtCore/QThreadStorage> - -#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<Fiber *> 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/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 += . |
