ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

support for simulating multi-threading.

The following is loosely based on an article by Simon Tatham: <http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html>. More...

Classes

struct  Common::CoroBaseContext
 The core of any coroutine context which captures the 'state' of a coroutine. More...
class  Common::CoroContextHolder
 Wrapper class which holds a pointer to a pointer to a CoroBaseContext. More...
struct  Common::PROCESS
 process structure More...
struct  Common::EVENT
 Event structure. More...
class  Common::CoroutineScheduler
 Creates and manages "processes" (really coroutines). More...

Defines

#define CoroScheduler   (Common::CoroutineScheduler::instance())
#define CORO_PARAM   Common::CoroContext &coroParam
 Methods that have been converted to being a coroutine should have this as the first parameter.
#define CORO_BEGIN_CONTEXT
 Begin the declaration of a coroutine context.
#define CORO_END_CONTEXT(x)   } *x = (CoroContextTag *)coroParam
 End the declaration of a coroutine context.
#define CORO_BEGIN_CODE(x)
 Begin the code section of a coroutine.
#define CORO_END_CODE
 End the code section of a coroutine.
#define CORO_SLEEP(delay)
 Sleep for the specified number of scheduler cycles.
#define CORO_GIVE_WAY   do { CoroScheduler.giveWay(); CORO_SLEEP(1); } while (0)
#define CORO_RESCHEDULE   do { CoroScheduler.reschedule(); CORO_SLEEP(1); } while (0)
#define CORO_KILL_SELF()   do { if (&coroParam != &Common::nullContext) { coroParam->_sleep = -1; } return; } while (0)
 Stop the currently running coroutine and all calling coroutines.
#define CORO_SUBCTX   coroParam->_subctx
 This macro is to be used in conjunction with CORO_INVOKE_ARGS and similar macros for calling coroutines-enabled subroutines.
#define CORO_INVOKE_ARGS(subCoro, ARGS)
 Invoke another coroutine.
#define CORO_INVOKE_ARGS_V(subCoro, RESULT, ARGS)
 Invoke another coroutine.
#define CORO_INVOKE_0(subCoroutine)   CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX))
 Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with no parameters.
#define CORO_INVOKE_1(subCoroutine, a0)   CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0))
 Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with one parameter.
#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 two parameters.
#define CORO_INVOKE_3(subCoroutine, a0, a1, a2)   CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0, a1, a2))
 Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with three parameters.
#define CORO_INVOKE_4(subCoroutine, a0, a1, a2, a3)   CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0, a1, a2, a3))
 Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with four parameters.
#define CORO_PARAM_SIZE   32
#define CORO_NUM_PROCESS   100
#define CORO_MAX_PROCESSES   100
#define CORO_MAX_PID_WAITING   5
#define CORO_INFINITE   0xffffffff
#define CORO_INVALID_PID_VALUE   0

Typedefs

typedef CoroBaseContext * Common::CoroContext
typedef void(* Common::CORO_ADDR )(CoroContext &, const void *)
 Coroutine parameter for methods converted to coroutines.
typedef PROCESS * Common::PPROCESS

Variables

CoroContext Common::nullContext = nullptr
 Helper null context instance.

Detailed Description

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.


Define Documentation

#define CORO_BEGIN_CODE (   x  ) 
Value:
if (&coroParam == &Common::nullContext) assert(!Common::nullContext); \
    if (!x) { coroParam = x = new CoroContextTag(); } \
    x->DUMMY = 0; \
    Common::CoroContextHolder tmpHolder(coroParam); \
    switch (coroParam->_line) { case 0:;

Begin the code section of a coroutine.

Parameters:
x name of the coroutine context
See also:
CORO_BEGIN_CODE

Definition at line 147 of file coroutines.h.

#define CORO_BEGIN_CONTEXT
Value:
struct CoroContextTag : Common::CoroBaseContext { \
 CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) { DUMMY = 0; } \
        int DUMMY

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 also:
CORO_END_CONTEXT
Note:
We declare a variable 'DUMMY' to allow the user to specify an 'empty' context, and so compilers won't complain about ";" following the macro.

Definition at line 130 of file coroutines.h.

#define CORO_END_CODE
Value:
if (&coroParam == &Common::nullContext) { \
        delete Common::nullContext; \
        Common::nullContext = NULL; \
    } \
    }

End the code section of a coroutine.

See also:
CORO_END_CODE

Definition at line 158 of file coroutines.h.

#define CORO_END_CONTEXT (   x  )     } *x = (CoroContextTag *)coroParam

End the declaration of a coroutine context.

Parameters:
x name of the coroutine context
See also:
CORO_BEGIN_CONTEXT

Definition at line 140 of file coroutines.h.

#define CORO_GIVE_WAY   do { CoroScheduler.giveWay(); CORO_SLEEP(1); } while (0)

Definition at line 176 of file coroutines.h.

#define CORO_INFINITE   0xffffffff

Definition at line 294 of file coroutines.h.

#define CORO_INVALID_PID_VALUE   0

Definition at line 295 of file coroutines.h.

#define CORO_INVOKE_0 (   subCoroutine  )     CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX))

Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with no parameters.

Definition at line 253 of file coroutines.h.

#define CORO_INVOKE_1 (   subCoroutine,
  a0 
)    CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0))

Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with one parameter.

Definition at line 260 of file coroutines.h.

#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 two parameters.

Definition at line 267 of file coroutines.h.

#define CORO_INVOKE_3 (   subCoroutine,
  a0,
  a1,
  a2 
)    CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0, a1, a2))

Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with three parameters.

Definition at line 274 of file coroutines.h.

#define CORO_INVOKE_4 (   subCoroutine,
  a0,
  a1,
  a2,
  a3 
)    CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0, a1, a2, a3))

Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine with four parameters.

Definition at line 281 of file coroutines.h.

#define CORO_INVOKE_ARGS (   subCoro,
  ARGS 
)
Value:
do { \
        coroParam->_line = __LINE__; \
        coroParam->_subctx = 0; \
        do { \
            subCoro ARGS; \
            if (!coroParam->_subctx) break; \
            coroParam->_sleep = coroParam->_subctx->_sleep; \
            assert(&coroParam != &Common::nullContext); \
            return; case __LINE__:; \
        } while (1); \
    } while (0)

Invoke another coroutine.

If the subcontext still exists after the coroutine is invoked, it has either yielded/slept or killed itself, and so we copy the _sleep value to our own context and return (execution will continue at the case statement below, where we loop and call the coroutine again). If the subcontext is null, the coroutine ended normally, and we can simply break out of the loop and continue execution.

Parameters:
subCoro name of the coroutine-enabled function to invoke
ARGS list of arguments to pass to subCoro
Note:
ARGS must be surrounded by parentheses, and the first argument in this list must always be CORO_SUBCTX. For example, the regular function call myFunc(a, b); becomes the following: CORO_INVOKE_ARGS(myFunc, (CORO_SUBCTX, a, b));

Definition at line 217 of file coroutines.h.

#define CORO_INVOKE_ARGS_V (   subCoro,
  RESULT,
  ARGS 
)
Value:
do { \
        coroParam->_line = __LINE__; \
        coroParam->_subctx = 0; \
        do { \
            subCoro ARGS; \
            if (!coroParam->_subctx) break; \
            coroParam->_sleep = coroParam->_subctx->_sleep; \
            assert(&coroParam != &Common::nullContext); \
            return RESULT; 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).

Definition at line 236 of file coroutines.h.

#define CORO_KILL_SELF (  )     do { if (&coroParam != &Common::nullContext) { coroParam->_sleep = -1; } return; } while (0)

Stop the currently running coroutine and all calling coroutines.

This sets _sleep to -1 rather than 0 so that the context doesn't get deleted by CoroContextHolder, since we want CORO_INVOKE_ARGS to propogate the _sleep value and return immediately (the scheduler will then delete the entire coroutine's state, including all subcontexts).

Definition at line 187 of file coroutines.h.

#define CORO_MAX_PID_WAITING   5

Definition at line 292 of file coroutines.h.

#define CORO_MAX_PROCESSES   100

Definition at line 291 of file coroutines.h.

#define CORO_NUM_PROCESS   100

Definition at line 290 of file coroutines.h.

#define CORO_PARAM   Common::CoroContext &coroParam

Methods that have been converted to being a coroutine should have this as the first parameter.

Definition at line 106 of file coroutines.h.

#define CORO_PARAM_SIZE   32

Definition at line 287 of file coroutines.h.

#define CORO_RESCHEDULE   do { CoroScheduler.reschedule(); CORO_SLEEP(1); } while (0)

Definition at line 177 of file coroutines.h.

#define CORO_SLEEP (   delay  ) 
Value:
do { \
        coroParam->_line = __LINE__; \
        coroParam->_sleep = delay; \
        assert(&coroParam != &Common::nullContext); \
        return; case __LINE__:; \
    } while (0)

Sleep for the specified number of scheduler cycles.

Definition at line 168 of file coroutines.h.

#define CORO_SUBCTX   coroParam->_subctx

This macro is to be used in conjunction with CORO_INVOKE_ARGS and similar macros for calling coroutines-enabled subroutines.

Definition at line 195 of file coroutines.h.

#define CoroScheduler   (Common::CoroutineScheduler::instance())

Definition at line 43 of file coroutines.h.


Typedef Documentation

typedef void(* Common::CORO_ADDR)(CoroContext &, const void *)

Coroutine parameter for methods converted to coroutines.

Definition at line 298 of file coroutines.h.

typedef CoroBaseContext* Common::CoroContext

Definition at line 71 of file coroutines.h.

typedef PROCESS* Common::PPROCESS

Definition at line 313 of file coroutines.h.


Variable Documentation

CoroContext Common::nullContext = nullptr

Helper null context instance.

This is a special constant that can be temporarily used as a parameter to call coroutine-ised methods from code that haven't yet been converted to being a coroutine, so code at least compiles correctly.

Be aware, though, that an error will occur if a coroutine that was passed the nullContext tries to sleep or yield control.

Definition at line 34 of file coroutines.cpp.



Generated on Sat Mar 23 2019 05:05:39 for ResidualVM by doxygen 1.7.1
curved edge   curved edge