diff options
author | Max Horn | 2009-04-09 17:07:24 +0000 |
---|---|---|
committer | Max Horn | 2009-04-09 17:07:24 +0000 |
commit | a2b5829101e256d5dfd1dc304ffc7d89b83c3e99 (patch) | |
tree | fff9527fdc75a56d66a6608eac3c4936590f4c70 | |
parent | da90b7e015970e30b8e95893b9f7745cf6a48176 (diff) | |
download | scummvm-rg350-a2b5829101e256d5dfd1dc304ffc7d89b83c3e99.tar.gz scummvm-rg350-a2b5829101e256d5dfd1dc304ffc7d89b83c3e99.tar.bz2 scummvm-rg350-a2b5829101e256d5dfd1dc304ffc7d89b83c3e99.zip |
TINSEL: Added some doxygen comments to the Tinsel coroutine code
svn-id: r39908
-rw-r--r-- | engines/tinsel/coroutine.h | 96 |
1 files changed, 87 insertions, 9 deletions
diff --git a/engines/tinsel/coroutine.h b/engines/tinsel/coroutine.h index d2c2c21b3a..aec2e6cdad 100644 --- a/engines/tinsel/coroutine.h +++ b/engines/tinsel/coroutine.h @@ -30,7 +30,9 @@ namespace Tinsel { -/* +/** + * @defgroup TinselCoroutines Coroutine support for Tinsel + * * The following is loosely based on an article by Simon Tatham: * <http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html>. * However, many improvements and tweaks have been made, in particular @@ -54,11 +56,11 @@ namespace Tinsel { * regressions, and will be helpful in the future when comparing things * against the original code base. */ - +//@{ /** * The core of any coroutine context which captures the 'state' of a coroutine. - * Private use only + * Private use only. */ struct CoroBaseContext { int _line; @@ -70,6 +72,8 @@ struct CoroBaseContext { typedef CoroBaseContext *CoroContext; + +// FIXME: Document this! extern CoroContext nullContext; /** @@ -83,7 +87,11 @@ extern CoroContext nullContext; class CoroContextHolder { CoroContext &_ctx; public: - CoroContextHolder(CoroContext &ctx) : _ctx(ctx) {} + CoroContextHolder(CoroContext &ctx) : _ctx(ctx) { + assert(ctx); + assert(ctx->_sleep >= 0); + ctx->_sleep = 0; + } ~CoroContextHolder() { if (_ctx && _ctx->_sleep == 0) { delete _ctx; @@ -98,22 +106,58 @@ public: #define CORO_SUBCTX coroParam->_subctx +/** + * Begin the declaration of a coroutine context. + * This allows declaring variables which are 'persistent' during the + * lifetime of the coroutine. An example use would be: + * + * CORO_BEGIN_CONTEXT; + * int var; + * char *foo; + * CORO_END_CONTEXT(_ctx); + * + * It is not possible to initialize variables here, due to the way this + * macro is implemented. Furthermore, to use the variables declared in + * the coroutine context, you have to access them via the context variable + * name that was specified as parameter to CORO_END_CONTEXT, e.g. + * _ctx->var = 0; + * + * @see CORO_END_CONTEXT + * + * @note We always declare a variable 'DUMMY' to allow the user to specify + * an 'empty' context. + */ #define CORO_BEGIN_CONTEXT struct CoroContextTag : CoroBaseContext { int DUMMY + +/** + * End the declaration of a coroutine context. + * @param x name of the coroutine context + * @see CORO_BEGIN_CONTEXT + */ #define CORO_END_CONTEXT(x) } *x = (CoroContextTag *)coroParam +/** + * Begin the code section of a coroutine. + * @param x name of the coroutine context + * @see CORO_BEGIN_CODE + */ #define CORO_BEGIN_CODE(x) \ if (&coroParam == &nullContext) assert(!nullContext);\ if (!x) {coroParam = x = new CoroContextTag();}\ - assert(coroParam);\ - assert(coroParam->_sleep >= 0);\ - coroParam->_sleep = 0;\ CoroContextHolder tmpHolder(coroParam);\ switch(coroParam->_line) { case 0:; +/** + * End the code section of a coroutine. + * @see CORO_END_CODE + */ #define CORO_END_CODE \ if (&coroParam == &nullContext) nullContext = NULL; \ } +/** + * Sleep for the specified number of scheduler cycles. + */ #define CORO_SLEEP(delay) do {\ coroParam->_line = __LINE__;\ coroParam->_sleep = delay;\ @@ -124,11 +168,18 @@ public: #define CORO_GIVE_WAY do { g_scheduler->giveWay(); CORO_SLEEP(1); } while (0) #define CORO_RESCHEDULE do { g_scheduler->reschedule(); CORO_SLEEP(1); } while (0) -/** Stop the currently running coroutine */ +/** + * Stop the currently running coroutine. + */ #define CORO_KILL_SELF() \ do { if (&coroParam != &nullContext) { coroParam->_sleep = -1; } return; } while (0) -/** Invoke another coroutine */ +/** + * Invoke another coroutine. + * + * What makes this tricky is that the coroutine we called my yield/sleep, + * and we need to deal with this adequately. + */ #define CORO_INVOKE_ARGS(subCoro, ARGS) \ do {\ coroParam->_line = __LINE__;\ @@ -141,6 +192,13 @@ public: return; case __LINE__:;\ } while (1);\ } while (0) + +/** + * Invoke another coroutine. Similar to CORO_INVOKE_ARGS, + * but allows specifying a return value which is returned + * if invoked coroutine yields (thus causing the current + * coroutine to yield, too). + */ #define CORO_INVOKE_ARGS_V(subCoro, RESULT, ARGS) \ do {\ coroParam->_line = __LINE__;\ @@ -154,15 +212,35 @@ public: } while (1);\ } while (0) +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with no parameters. + */ #define CORO_INVOKE_0(subCoroutine) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with one parameter. + */ #define CORO_INVOKE_1(subCoroutine, a0) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with two parameters. + */ #define CORO_INVOKE_2(subCoroutine, a0,a1) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with three parameters. + */ #define CORO_INVOKE_3(subCoroutine, a0,a1,a2) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2)) +//@} } // end of namespace Tinsel |