aboutsummaryrefslogtreecommitdiff
path: root/engines/tinsel/coroutine.h
diff options
context:
space:
mode:
authorMax Horn2008-07-24 08:59:17 +0000
committerMax Horn2008-07-24 08:59:17 +0000
commit69dac1d4f22f9a63a5a9030d4405ba071e5e8b89 (patch)
tree82f7bd95c3a03b3d4e363e26eecdc36fe3e8b600 /engines/tinsel/coroutine.h
parent627e0c277426b02153b79c82616ae7f351ad5bc3 (diff)
downloadscummvm-rg350-69dac1d4f22f9a63a5a9030d4405ba071e5e8b89.tar.gz
scummvm-rg350-69dac1d4f22f9a63a5a9030d4405ba071e5e8b89.tar.bz2
scummvm-rg350-69dac1d4f22f9a63a5a9030d4405ba071e5e8b89.zip
Moved scheduler / process managment code into a new class Scheduler
svn-id: r33259
Diffstat (limited to 'engines/tinsel/coroutine.h')
-rw-r--r--engines/tinsel/coroutine.h69
1 files changed, 46 insertions, 23 deletions
diff --git a/engines/tinsel/coroutine.h b/engines/tinsel/coroutine.h
index 4a8997fe00..e0292735bb 100644
--- a/engines/tinsel/coroutine.h
+++ b/engines/tinsel/coroutine.h
@@ -30,15 +30,36 @@
namespace Tinsel {
-// The following is loosely based on <http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html>,
-// Proper credit to Simon Tatham shall be given.
-
/*
+ * 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
+ * by taking advantage of C++ features not available in C.
+ *
+ * Why is this code here? Well, the Tinsel engine apparently used
+ * setjmp/longjmp based coroutines as a core tool from the start, and
+ * so they are deeply ingrained into the whole code base. When we
+ * started to get Tinsel ready for ScummVM, we had to deal with that.
+ * It soon got clear that we could not simply rewrite the code to work
+ * without some form of coroutines. While possible in principle, it
+ * would have meant a major restructuring of the entire code base, a
+ * rather daunting task. Also, it would have very likely introduced
+ * tons of regressons.
+ *
+ * So instead of getting rid of the coroutines, we chose to implement
+ * them in an alternate way, using Simon Tatham's trick as described
+ * above. While the trick is dirty, the result seems to be clear enough,
+ * we hope; plus, it allowed us to stay relatively close to the
+ * original structure of the code, which made it easier to avoid
+ * regressions, and will be helpful in the future when comparing things
+ * against the original code base.
+ */
- * `ccr' macros for re-entrant coroutines.
+/**
+ * The core of any coroutine context which captures the 'state' of a coroutine.
+ * Private use only
*/
-
struct CoroBaseContext {
int _line;
int _sleep;
@@ -53,16 +74,28 @@ typedef CoroBaseContext *CoroContext;
/**
* Wrapper class which holds a pointer to a pointer to a CoroBaseContext.
* The interesting part is the destructor, which kills the context being held,
- * but ONLY if the _sleep val of that context is zero.
+ * but ONLY if the _sleep val of that context is zero. This way, a coroutine
+ * can just 'return' w/o having to worry about freeing the allocated context
+ * (in Simon Tatham's original code, one had to use a special macro to
+ * return from a coroutine).
*/
-struct CoroContextHolder {
+class CoroContextHolder {
CoroContext &_ctx;
+public:
CoroContextHolder(CoroContext &ctx) : _ctx(ctx) {}
- ~CoroContextHolder() { if (_ctx && _ctx->_sleep == 0) { delete _ctx; _ctx = 0; } }
+ ~CoroContextHolder() {
+ if (_ctx && _ctx->_sleep == 0) {
+ delete _ctx;
+ _ctx = 0;
+ }
+ }
};
+
#define CORO_PARAM CoroContext &coroParam
+#define CORO_SUBCTX coroParam->_subctx
+
#define CORO_BEGIN_CONTEXT struct CoroContextTag : CoroBaseContext { int DUMMY
#define CORO_END_CONTEXT(x) } *x = (CoroContextTag *)coroParam
@@ -80,19 +113,18 @@ struct CoroContextHolder {
#define CORO_SLEEP(delay) \
do {\
- coroParam->_line=__LINE__;\
- coroParam->_sleep=delay;\
+ coroParam->_line = __LINE__;\
+ coroParam->_sleep = delay;\
return; case __LINE__:;\
} while (0)
-// Stop the currently running coroutine
+/** Stop the currently running coroutine */
#define CORO_KILL_SELF() do { coroParam->_sleep = -1; return; } while(0)
-//#define CORO_ABORT() do { delete (ctx); ctx = 0; } while (0)
-
+/** Invoke another coroutine */
#define CORO_INVOKE_ARGS(subCoro, ARGS) \
do {\
- coroParam->_line=__LINE__;\
+ coroParam->_line = __LINE__;\
coroParam->_subctx = 0;\
do {\
subCoro ARGS;\
@@ -102,21 +134,12 @@ struct CoroContextHolder {
} while(1);\
} while (0)
-#define CORO_SUBCTX coroParam->_subctx
-
#define CORO_INVOKE_0(subCoroutine) \
CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX))
#define CORO_INVOKE_1(subCoroutine, a0) \
CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0))
#define CORO_INVOKE_2(subCoroutine, a0,a1) \
CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1))
-#define CORO_INVOKE_3(subCoroutine, a0,a1,a2) \
- CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2))
-#define CORO_INVOKE_4(subCoroutine, a0,a1,a2,a3) \
- CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2,a3))
-#define CORO_INVOKE_5(subCoroutine, a0,a1,a2,a3,a4) \
- CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2,a3,a4))
-
} // end of namespace Tinsel