diff options
-rw-r--r-- | common/coroutines.cpp | 34 | ||||
-rw-r--r-- | common/coroutines.h | 203 |
2 files changed, 118 insertions, 119 deletions
diff --git a/common/coroutines.cpp b/common/coroutines.cpp index 102db8d26d..241d31e0d7 100644 --- a/common/coroutines.cpp +++ b/common/coroutines.cpp @@ -34,7 +34,6 @@ CoroContext nullContext = NULL; DECLARE_SINGLETON(CoroutineScheduler); - #ifdef COROUTINE_DEBUG namespace { /** Count of active coroutines */ @@ -63,13 +62,13 @@ static void displayCoroStats() { if (!s_coroFuncs) return; for (CoroHashMap::const_iterator it = s_coroFuncs->begin(); - it != s_coroFuncs->end(); ++it) { + it != s_coroFuncs->end(); ++it) { if (it->_value != 0) debug(" %3d x %s", it->_value, it->_key.c_str()); } } -} +} // End of anonymous namespace #endif CoroBaseContext::CoroBaseContext(const char *func) @@ -86,7 +85,7 @@ CoroBaseContext::~CoroBaseContext() { s_coroCount--; changeCoroStats(_funcName, -1); debug("Deleting coro in %s at %p (subctx %p)", - _funcName, (void *)this, (void *)_subctx); + _funcName, (void *)this, (void *)_subctx); displayCoroStats(); #endif delete _subctx; @@ -133,11 +132,10 @@ CoroutineScheduler::~CoroutineScheduler() { // Clear the event list Common::List<EVENT *>::iterator i; for (i = _events.begin(); i != _events.end(); ++i) - delete (*i); + delete *i; } void CoroutineScheduler::reset() { - #ifdef DEBUG // clear number of process in use numProcs = 0; @@ -179,14 +177,14 @@ void CoroutineScheduler::reset() { } -#ifdef DEBUG +#ifdef DEBUG void CoroutineScheduler::printStats() { debug("%i process of %i used", maxProcs, CORO_NUM_PROCESS); } #endif #ifdef DEBUG -void CoroutineScheduler::CheckStack() { +void CoroutineScheduler::checkStack() { Common::List<PROCESS *> pList; // Check both the active and free process lists @@ -354,7 +352,7 @@ void CoroutineScheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duratio // Presume it will expire *expired = true; - // Outer loop for doing checks until expiry + // Outer loop for doing checks until expiry while (g_system->getMillis() <= _ctx->endTime) { // Check to see if a process or event with the given Id exists _ctx->pProcess = getProcess(pid); @@ -368,7 +366,7 @@ void CoroutineScheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duratio break; } - // If a process was found, don't go into the if statement, and keep waiting. + // If a process was found, don't go into the if statement, and keep waiting. // Likewise if it's an event that's not yet signalled if ((_ctx->pEvent != NULL) && _ctx->pEvent->signalled) { // Unless the event is flagged for manual reset, reset it now @@ -390,8 +388,8 @@ void CoroutineScheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duratio CORO_END_CODE; } -void CoroutineScheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, - uint32 duration, bool *expired) { +void CoroutineScheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, + uint32 duration, bool *expired) { if (!pCurrent) error("Called CoroutineScheduler::waitForMultipleObjects from the main process"); @@ -415,7 +413,7 @@ void CoroutineScheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 * // Presume that delay will expire *expired = true; - // Outer loop for doing checks until expiry + // Outer loop for doing checks until expiry while (g_system->getMillis() <= _ctx->endTime) { _ctx->signalled = bWaitAll; @@ -471,7 +469,7 @@ void CoroutineScheduler::sleep(CORO_PARAM, uint32 duration) { _ctx->endTime = g_system->getMillis() + duration; - // Outer loop for doing checks until expiry + // Outer loop for doing checks until expiry while (g_system->getMillis() < _ctx->endTime) { // Sleep until the next cycle CORO_SLEEP(1); @@ -510,7 +508,7 @@ PROCESS *CoroutineScheduler::createProcess(uint32 pid, CORO_ADDR coroAddr, const pCurrent->pNext = pProc; pProc->pPrevious = pCurrent; - } else { // no active processes, place process at head of list + } else { // no active processes, place process at head of list pProc->pNext = active->pNext; pProc->pPrevious = active; @@ -604,7 +602,7 @@ int CoroutineScheduler::getCurrentPID() const { int CoroutineScheduler::killMatchingProcess(uint32 pidKill, int pidMask) { int numKilled = 0; - PROCESS *pProc, *pPrev; // process list pointers + PROCESS *pProc, *pPrev; // process list pointers for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { if ((pProc->pid & (uint32)pidMask) == pidKill) { @@ -709,10 +707,10 @@ void CoroutineScheduler::pulseEvent(uint32 pidEvent) { EVENT *evt = getEvent(pidEvent); if (!evt) return; - + // Set the event as true evt->signalled = true; - + // start dispatching active process list for any processes that are currently waiting PROCESS *pOriginal = pCurrent; PROCESS *pNext; diff --git a/common/coroutines.h b/common/coroutines.h index f5519902dd..3b8b1a77f9 100644 --- a/common/coroutines.h +++ b/common/coroutines.h @@ -23,7 +23,7 @@ #define COMMON_COROUTINES_H #include "common/scummsys.h" -#include "common/util.h" // for SCUMMVM_CURRENT_FUNCTION +#include "common/util.h" // for SCUMMVM_CURRENT_FUNCTION #include "common/list.h" #include "common/singleton.h" @@ -133,42 +133,43 @@ public: /** * End the declaration of a coroutine context. - * @param x name of the 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 + * @param x name of the coroutine context * @see CORO_BEGIN_CODE */ #define CORO_BEGIN_CODE(x) \ - if (&coroParam == &Common::nullContext) assert(!Common::nullContext);\ - if (!x) {coroParam = x = new CoroContextTag();}\ - Common::CoroContextHolder tmpHolder(coroParam);\ - switch (coroParam->_line) { case 0:; + if (&coroParam == &Common::nullContext) assert(!Common::nullContext); \ + if (!x) { coroParam = x = new CoroContextTag(); } \ + Common::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 == &Common::nullContext) { \ - delete Common::nullContext; \ - Common::nullContext = NULL; \ - } \ - } + if (&coroParam == &Common::nullContext) { \ + delete Common::nullContext; \ + Common::nullContext = NULL; \ + } \ + } /** * Sleep for the specified number of scheduler cycles. */ -#define CORO_SLEEP(delay) do {\ - coroParam->_line = __LINE__;\ - coroParam->_sleep = delay;\ - assert(&coroParam != &Common::nullContext);\ - return; case __LINE__:;\ - } while (0) +#define CORO_SLEEP(delay) \ + do { \ + coroParam->_line = __LINE__; \ + coroParam->_sleep = delay; \ + assert(&coroParam != &Common::nullContext); \ + return; case __LINE__:; \ + } while (0) #define CORO_GIVE_WAY do { CoroScheduler.giveWay(); CORO_SLEEP(1); } while (0) #define CORO_RESCHEDULE do { CoroScheduler.reschedule(); CORO_SLEEP(1); } while (0) @@ -182,7 +183,7 @@ public: * then delete the entire coroutine's state, including all subcontexts). */ #define CORO_KILL_SELF() \ - do { if (&coroParam != &Common::nullContext) { coroParam->_sleep = -1; } return; } while (0) + do { if (&coroParam != &Common::nullContext) { coroParam->_sleep = -1; } return; } while (0) /** @@ -201,8 +202,8 @@ public: * If the subcontext is null, the coroutine ended normally, and we can * simply break out of the loop and continue execution. * - * @param subCoro name of the coroutine-enabled function to invoke - * @param ARGS list of arguments to pass to subCoro + * @param subCoro name of the coroutine-enabled function to invoke + * @param 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 @@ -211,18 +212,18 @@ public: * becomes the following: * CORO_INVOKE_ARGS(myFunc, (CORO_SUBCTX, a, b)); */ -#define CORO_INVOKE_ARGS(subCoro, ARGS) \ - 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) +#define CORO_INVOKE_ARGS(subCoro, ARGS) \ + 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. Similar to CORO_INVOKE_ARGS, @@ -230,62 +231,62 @@ public: * if invoked coroutine yields (thus causing the current * coroutine to yield, too). */ -#define CORO_INVOKE_ARGS_V(subCoro, RESULT, ARGS) \ - 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) +#define CORO_INVOKE_ARGS_V(subCoro, RESULT, ARGS) \ + 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) /** * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine * with no parameters. */ #define CORO_INVOKE_0(subCoroutine) \ - CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX)) + 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)) + 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)) + 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)) + CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0, a1, a2)) /** * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine * with four parameters. */ #define CORO_INVOKE_4(subCoroutine, a0,a1,a2,a3) \ - CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2,a3)) + CORO_INVOKE_ARGS(subCoroutine, (CORO_SUBCTX, a0, a1, a2, a3)) // the size of process specific info -#define CORO_PARAM_SIZE 32 +#define CORO_PARAM_SIZE 32 // the maximum number of processes -#define CORO_NUM_PROCESS 100 -#define CORO_MAX_PROCESSES 100 +#define CORO_NUM_PROCESS 100 +#define CORO_MAX_PROCESSES 100 #define CORO_MAX_PID_WAITING 5 #define CORO_INFINITE 0xffffffff @@ -296,16 +297,16 @@ typedef void (*CORO_ADDR)(CoroContext &, const void *); /** process structure */ struct PROCESS { - PROCESS *pNext; ///< pointer to next process in active or free list - PROCESS *pPrevious; ///< pointer to previous process in active or free list + PROCESS *pNext; ///< pointer to next process in active or free list + PROCESS *pPrevious; ///< pointer to previous process in active or free list - CoroContext state; ///< the state of the coroutine - CORO_ADDR coroAddr; ///< the entry point of the coroutine + CoroContext state; ///< the state of the coroutine + CORO_ADDR coroAddr; ///< the entry point of the coroutine - int sleepTime; ///< number of scheduler cycles to sleep - uint32 pid; ///< process ID - uint32 pidWaiting[CORO_MAX_PID_WAITING]; ///< Process ID(s) process is currently waiting on - char param[CORO_PARAM_SIZE]; ///< process specific info + int sleepTime; ///< number of scheduler cycles to sleep + uint32 pid; ///< process ID + uint32 pidWaiting[CORO_MAX_PID_WAITING]; ///< Process ID(s) process is currently waiting on + char param[CORO_PARAM_SIZE]; ///< process specific info }; typedef PROCESS *PPROCESS; @@ -321,7 +322,7 @@ struct EVENT { /** * Creates and manages "processes" (really coroutines). */ -class CoroutineScheduler: public Singleton<CoroutineScheduler> { +class CoroutineScheduler : public Singleton<CoroutineScheduler> { public: /** Pointer to a function of the form "void function(PPROCESS)" */ typedef void (*VFPTRPP)(PROCESS *); @@ -355,7 +356,7 @@ private: * Checks both the active and free process list to insure all the links are valid, * and that no processes have been lost */ - void CheckStack(); + void checkStack(); #endif /** @@ -382,12 +383,12 @@ public: */ void reset(); - #ifdef DEBUG +#ifdef DEBUG /** * Shows the maximum number of process used at once. */ void printStats(); - #endif +#endif /** * Give all active processes a chance to run @@ -408,71 +409,71 @@ public: /** * Moves the specified process to the end of the dispatch queue * allowing it to run again within the current game cycle. - * @param pGiveProc Which process + * @param pGiveProc Which process */ void giveWay(PPROCESS pReSchedProc = NULL); /** * Continously makes a given process wait for another process to finish or event to signal. * - * @param pid Process/Event identifier - * @param duration Duration in milliseconds - * @param expired If specified, set to true if delay period expired + * @param pid Process/Event identifier + * @param duration Duration in milliseconds + * @param expired If specified, set to true if delay period expired */ void waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired = NULL); /** * Continously makes a given process wait for given prcesses to finished or events to be set * - * @param nCount Number of Id's being passed - * @param evtList List of pids to wait for - * @param bWaitAll Specifies whether all or any of the processes/events - * @param duration Duration in milliseconds - * @param expired Set to true if delay period expired + * @param nCount Number of Id's being passed + * @param evtList List of pids to wait for + * @param bWaitAll Specifies whether all or any of the processes/events + * @param duration Duration in milliseconds + * @param expired Set to true if delay period expired */ - void waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, - uint32 duration, bool *expired = NULL); + void waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, + uint32 duration, bool *expired = NULL); /** * Make the active process sleep for the given duration in milliseconds * - * @param duration Duration in milliseconds - * @remarks This duration won't be precise, since it relies on the frequency the + * @param duration Duration in milliseconds + * @remarks This duration won't be precise, since it relies on the frequency the * scheduler is called. */ void sleep(CORO_PARAM, uint32 duration); - + /** * Creates a new process. * - * @param pid process identifier - * @param coroAddr Coroutine start address - * @param pParam Process specific info - * @param sizeParam Size of process specific info + * @param pid process identifier + * @param coroAddr Coroutine start address + * @param pParam Process specific info + * @param sizeParam Size of process specific info */ PROCESS *createProcess(uint32 pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam); /** * Creates a new process with an auto-incrementing Process Id. * - * @param coroAddr Coroutine start address - * @param pParam Process specific info - * @param sizeParam Size of process specific info + * @param coroAddr Coroutine start address + * @param pParam Process specific info + * @param sizeParam Size of process specific info */ uint32 createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam); /** * Creates a new process with an auto-incrementing Process Id, and a single pointer parameter. * - * @param coroAddr Coroutine start address - * @param pParam Process specific info + * @param coroAddr Coroutine start address + * @param pParam Process specific info */ uint32 createProcess(CORO_ADDR coroAddr, const void *pParam); /** * Kills the specified process. * - * @param pKillProc Which process to kill + * @param pKillProc Which process to kill */ void killProcess(PROCESS *pKillProc); @@ -490,9 +491,9 @@ public: * Kills any process matching the specified PID. The current * process cannot be killed. * - * @param pidKill Process identifier of process to kill - * @param pidMask Mask to apply to process identifiers before comparison - * @return The number of processes killed is returned. + * @param pidKill Process identifier of process to kill + * @param pidMask Mask to apply to process identifiers before comparison + * @return The number of processes killed is returned. */ int killMatchingProcess(uint32 pidKill, int pidMask = -1); @@ -503,7 +504,7 @@ public: * called by killProcess() to allow the resource allocator to free * resources allocated to the dying process. * - * @param pFunc Function to be called by killProcess() + * @param pFunc Function to be called by killProcess() */ void setResourceCallback(VFPTRPP pFunc); @@ -511,29 +512,29 @@ public: /** * Creates a new event (semaphore) object * - * @param bManualReset Events needs to be manually reset. Otherwise, + * @param bManualReset Events needs to be manually reset. Otherwise, * events will be automatically reset after a * process waits on the event finishes - * @param bInitialState Specifies whether the event is signalled or not + * @param bInitialState Specifies whether the event is signalled or not * initially */ uint32 createEvent(bool bManualReset, bool bInitialState); /** * Destroys the given event - * @param pidEvent Event Process Id + * @param pidEvent Event Process Id */ void closeEvent(uint32 pidEvent); /** * Sets the event - * @param pidEvent Event Process Id + * @param pidEvent Event Process Id */ void setEvent(uint32 pidEvent); /** * Resets the event - * @param pidEvent Event Process Id + * @param pidEvent Event Process Id */ void resetEvent(uint32 pidEvent); @@ -542,9 +543,9 @@ public: * processes,allowing any processes waiting on the event to be fired. It * then immediately resets the event again. * - * @param pidEvent Event Process Id + * @param pidEvent Event Process Id * - * @remarks Should not be run inside of another process + * @remarks Should not be run inside of another process */ void pulseEvent(uint32 pidEvent); }; @@ -553,4 +554,4 @@ public: } // end of namespace Common -#endif // COMMON_COROUTINES_H +#endif // COMMON_COROUTINES_H |