TONY: Further conversion of initially launched threads to processes.

This includes all the dependent routines that they call.
This commit is contained in:
Paul Gilbert 2012-05-06 15:18:03 +10:00
parent 20a47ff7c9
commit 770e55d065
11 changed files with 284 additions and 200 deletions

View file

@ -49,6 +49,7 @@
#define TONY_ADV_H
#include "tony/mpal/memory.h"
#include "tony/coroutine.h"
#include "tony/gfxcore.h"
@ -91,7 +92,7 @@ enum RMTonyAction {
// Funzioni globali
HANDLE MainLoadLocation(int nLoc, RMPoint pt, RMPoint start);
HANDLE MainUnloadLocation(bool bDoOnExit);
void MainUnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result);
void MainLinkGraphicTask(RMGfxTask *task);
void MainFreeze(void);
void MainUnfreeze(void);

View file

@ -72,7 +72,7 @@ RMInventory *Inventory;
RMInput *Input;
HANDLE (*LoadLocation)(int, RMPoint, RMPoint start);
HANDLE (*UnloadLocation)(bool bDoOnExit);
void (*UnloadLocation)(CORO_PARAM, bool bDoOnExit, HANDLE *result);
void (*LinkGraphicTask)(RMGfxTask *task);
void (*Freeze)(void);
void (*Unfreeze)(void);
@ -505,20 +505,27 @@ RMPoint SFM_pt;
int SFM_nLoc;
DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
RMMessage msg(nMsg);
CORO_BEGIN_CONTEXT;
RMMessage *msg;
RMGfxClearTask clear;
int i;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->msg = new RMMessage(nMsg);
SFM_nLoc = Loc->TEMPGetNumLoc();
SFM_pt = Tony->Position();
if (bSkipIdle) return;
if (bSkipIdle)
return;
UnloadLocation(false);
CORO_INVOKE_2(UnloadLocation, false, NULL);
Tony->Hide();
Unfreeze();
for (i = 0; i < msg.NumPeriods() && !bSkipIdle; i++) {
for (_ctx->i = 0; _ctx->i < _ctx->msg->NumPeriods() && !bSkipIdle; _ctx->i++) {
RMTextDialog text;
text.SetInput(Input);
@ -534,9 +541,9 @@ DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32
// Scrive il testo
if (nFont == 0)
text.WriteText(msg[i],1);
text.WriteText((*_ctx->msg)[_ctx->i], 1);
else if (nFont == 1)
text.WriteText(msg[i],0);
text.WriteText((*_ctx->msg)[_ctx->i], 0);
// Setta la posizione
text.SetPosition(RMPoint(320, 240));
@ -545,13 +552,17 @@ DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32
text.ForceTime();
// Registra il testo
LinkGraphicTask(&clear);
LinkGraphicTask(&_ctx->clear);
LinkGraphicTask(&text);
// Aspetta la fine della visualizzazione
text.SetCustomSkipHandle(hSkipIdle);
text.WaitForEndDisplay();
}
delete _ctx->msg;
CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(ClearScreen)(CORO_PARAM, uint32, uint32, uint32, uint32) {
@ -592,6 +603,11 @@ DECLARE_CUSTOM_FUNCTION(NoOcchioDiBue)(CORO_PARAM, uint32, uint32, uint32, uint3
}
DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (!bNoOcchioDiBue) {
InitWipe(1);
WaitWipeEnd();
@ -600,13 +616,19 @@ DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint3
_vm->StopMusic(4);
// On Exit e lascia freezzato
UnloadLocation(true);
CORO_INVOKE_2(UnloadLocation, true, NULL);
Unfreeze();
CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
CORO_BEGIN_CONTEXT;
HANDLE h;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (!bNoOcchioDiBue) {
InitWipe(1);
@ -618,7 +640,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
}
// On Exit e lascia freezzato
UnloadLocation(true);
CORO_INVOKE_2(UnloadLocation, true, NULL);
curChangedHotspot = 0;
if (bUseStartPos != 0)
@ -639,7 +661,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
Unfreeze();
h = mpalQueryDoAction(0, nLoc,0);
_ctx->h = mpalQueryDoAction(0, nLoc, 0);
if (!bNoOcchioDiBue) {
WaitWipeEnd();
@ -649,9 +671,10 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
bNoOcchioDiBue = false;
// On Enter?
if (h != INVALID_HANDLE_VALUE)
WaitForSingleObject(h,INFINITE);
if (_ctx->h != INVALID_HANDLE_VALUE)
WaitForSingleObject(_ctx->h, INFINITE);
CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(SetLocStartPosition)(CORO_PARAM, uint32 nLoc, uint32 lX, uint32 lY, uint32) {

View file

@ -96,8 +96,8 @@ HANDLE MainLoadLocation(int nLoc, RMPoint pt, RMPoint start) {
return _vm->GetEngine()->LoadLocation(nLoc, pt,start);
}
HANDLE MainUnloadLocation(bool bDoOnExit) {
return _vm->GetEngine()->UnloadLocation(bDoOnExit);
void MainUnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result) {
_vm->GetEngine()->UnloadLocation(coroParam, bDoOnExit, result);
}
void MainLinkGraphicTask(RMGfxTask *task) {

View file

@ -65,13 +65,21 @@ extern bool bSkipSfxNoLoop;
bool bIdleExited;
void ExitAllIdles(int nCurLoc) {
void ExitAllIdles(CORO_PARAM, int nCurLoc) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// Chiude le idle
bSkipSfxNoLoop = true;
mpalEndIdlePoll(nCurLoc);
CORO_INVOKE_2(mpalEndIdlePoll, nCurLoc, NULL);
bIdleExited = true;
bSkipSfxNoLoop = false;
ExitThread(0);
CORO_END_CODE;
}
RMGfxEngine::RMGfxEngine() {
@ -514,17 +522,21 @@ HANDLE RMGfxEngine::LoadLocation(int nLoc, RMPoint ptTonyStart, RMPoint start) {
return INVALID_HANDLE_VALUE; //mpalQueryDoAction(0,m_nCurLoc,0);
}
HANDLE RMGfxEngine::UnloadLocation(bool bDoOnExit) {
void RMGfxEngine::UnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result) {
CORO_BEGIN_CONTEXT;
HANDLE h;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// Scarica tutta la memoria della locazione
mpalEndIdlePoll(m_nCurLoc);
CORO_INVOKE_2(mpalEndIdlePoll, m_nCurLoc, NULL);
// On Exit?
if (bDoOnExit) {
h = mpalQueryDoAction(1, m_nCurLoc, 0);
if (h != INVALID_HANDLE_VALUE)
WaitForSingleObject(h, INFINITE);
_ctx->h = mpalQueryDoAction(1, m_nCurLoc, 0);
if (_ctx->h != INVALID_HANDLE_VALUE)
WaitForSingleObject(_ctx->h, INFINITE);
}
MainFreeze();
@ -534,7 +546,10 @@ HANDLE RMGfxEngine::UnloadLocation(bool bDoOnExit) {
m_bigBuf.ClearOT();
m_loc.Unload();
return INVALID_HANDLE_VALUE;
if (result != NULL)
*result = INVALID_HANDLE_VALUE;
CORO_END_CODE;
}
void RMGfxEngine::Init(/*HINSTANCE hInst*/) {
@ -930,7 +945,7 @@ void RMGfxEngine::LoadState(const char *fn) {
delete f;
UnloadLocation(false);
UnloadLocation(nullContext, false, NULL);
LoadLocation(loc,tp,RMPoint(-1, -1));
m_tony.SetPattern(RMTony::PAT_STANDRIGHT);
MainUnfreeze();

View file

@ -138,7 +138,7 @@ public:
// Manage a location
HANDLE LoadLocation(int nLoc, RMPoint ptTonyStart, RMPoint start);
HANDLE UnloadLocation(bool bDoOnExit=true);
void UnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result);
// Freeze and unfreeze
void Freeze(void);

View file

@ -138,7 +138,7 @@ bool bExecutingDialog;
uint32 nPollingLocations[MAXPOLLINGLOCATIONS];
HANDLE hEndPollingLocations[MAXPOLLINGLOCATIONS];
HANDLE PollingThreads[MAXPOLLINGLOCATIONS];
uint32 PollingThreads[MAXPOLLINGLOCATIONS];
HANDLE hAskChoice;
HANDLE hDoneChoice;
@ -996,7 +996,7 @@ void ShutUpActionThread(CORO_PARAM, const void *param) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
int pid = *(const int *)param;
uint32 pid = *(const uint32 *)param;
CORO_BEGIN_CODE(_ctx);
@ -1021,17 +1021,7 @@ void ShutUpActionThread(CORO_PARAM, const void *param) {
*
\****************************************************************************/
void PASCAL LocationPollThread(uint32 id) {
uint32 *il;
int i,j,k;
int numitems;
int nRealItems;
LPMPALITEM curItem,newItem;
int nIdleActions;
uint32 curTime;
uint32 dwSleepTime;
uint32 dwId;
void LocationPollThread(CORO_PARAM, const void *param) {
typedef struct {
uint32 nItem, nAction;
@ -1046,59 +1036,77 @@ void PASCAL LocationPollThread(uint32 id) {
typedef struct {
uint32 nItem;
HANDLE hThread;
uint32 hThread;
} MYTHREAD;
CORO_BEGIN_CONTEXT;
uint32 *il;
int i, j, k;
int numitems;
int nRealItems;
LPMPALITEM curItem,newItem;
int nIdleActions;
uint32 curTime;
uint32 dwSleepTime;
uint32 dwId;
int ord;
bool delayExpired;
MYACTION *MyActions;
MYTHREAD *MyThreads;
CORO_END_CONTEXT(_ctx);
uint32 id = *((const uint32 *)param);
CORO_BEGIN_CODE(_ctx);
/* Tanto per cominciare, e' necessario richiedere la lista degli item
presenti nella locazione. */
il = mpalQueryItemList(nPollingLocations[id]);
_ctx->il = mpalQueryItemList(nPollingLocations[id]);
/* Contiamo gli items */
for (numitems = 0; il[numitems] != 0; numitems++)
for (_ctx->numitems = 0; _ctx->il[_ctx->numitems] != 0; _ctx->numitems++)
;
/* Cerchiamo gli items della locazione senza idle actions e li eliminiamo
dalla lista */
LockItems();
nIdleActions = 0;
nRealItems = 0;
for (i = 0; i < numitems; i++) {
int ord = itemGetOrderFromNum(il[i]);
_ctx->nIdleActions = 0;
_ctx->nRealItems = 0;
for (_ctx->i = 0; _ctx->i < _ctx->numitems; _ctx->i++) {
_ctx->ord = itemGetOrderFromNum(_ctx->il[_ctx->i]);
if (ord == -1) continue;
if (_ctx->ord == -1) continue;
curItem = lpmiItems + ord;
_ctx->curItem = lpmiItems + _ctx->ord;
k = 0;
for (j = 0; j < curItem->nActions; j++)
if (curItem->Action[j].num == 0xFF)
k++;
_ctx->k = 0;
for (_ctx->j = 0; _ctx->j < _ctx->curItem->nActions; _ctx->j++)
if (_ctx->curItem->Action[_ctx->j].num == 0xFF)
_ctx->k++;
nIdleActions += k;
_ctx->nIdleActions += _ctx->k;
if (k == 0)
if (_ctx->k == 0)
/* Possiamo eliminare questo item dalla lista */
il[i] = (uint32)NULL;
_ctx->il[_ctx->i] = (uint32)NULL;
else
nRealItems++;
_ctx->nRealItems++;
}
UnlockItems();
/* Se non e' rimasto nessuno possiamo uscire */
if (nRealItems == 0) {
GlobalFree(il);
ExitThread(0);
// _endthread();
if (_ctx->nRealItems == 0) {
GlobalFree(_ctx->il);
CORO_KILL_SELF();
return;
}
MyThreads=(MYTHREAD *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nRealItems * sizeof(MYTHREAD));
if (MyThreads == NULL) {
GlobalFree(il);
ExitThread(0);
// _endthread();
_ctx->MyThreads = (MYTHREAD *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _ctx->nRealItems * sizeof(MYTHREAD));
if (_ctx->MyThreads == NULL) {
GlobalFree(_ctx->il);
CORO_KILL_SELF();
return;
}
/* Inizializziamo le routine random */
@ -1108,142 +1116,147 @@ void PASCAL LocationPollThread(uint32 id) {
/* Abbiamo appurato che esiste almeno un item che contiene idle actions.
Ora creaiamo le copie speculari delle idle actions */
MyActions = (MYACTION *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nIdleActions * sizeof(MYACTION));
if (MyActions == NULL) {
GlobalFree(MyThreads);
GlobalFree(il);
ExitThread(0);
// _endthread();
_ctx->MyActions = (MYACTION *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _ctx->nIdleActions * sizeof(MYACTION));
if (_ctx->MyActions == NULL) {
GlobalFree(_ctx->MyThreads);
GlobalFree(_ctx->il);
CORO_KILL_SELF();
return;
}
LockItems();
k = 0;
_ctx->k = 0;
for (i = 0; i < numitems; i++) {
if (il[i] == 0)
for (_ctx->i = 0; _ctx->i < _ctx->numitems; _ctx->i++) {
if (_ctx->il[_ctx->i] == 0)
continue;
curItem = lpmiItems + itemGetOrderFromNum(il[i]);
_ctx->curItem = lpmiItems + itemGetOrderFromNum(_ctx->il[_ctx->i]);
for (j = 0; j < curItem->nActions; j++)
if (curItem->Action[j].num == 0xFF) {
MyActions[k].nItem = il[i];
MyActions[k].nAction = j;
for (_ctx->j = 0; _ctx->j < _ctx->curItem->nActions; _ctx->j++)
if (_ctx->curItem->Action[_ctx->j].num == 0xFF) {
_ctx->MyActions[_ctx->k].nItem = _ctx->il[_ctx->i];
_ctx->MyActions[_ctx->k].nAction = _ctx->j;
MyActions[k].wTime = curItem->Action[j].wTime;
MyActions[k].perc = curItem->Action[j].perc;
MyActions[k].when = curItem->Action[j].when;
MyActions[k].nCmds = curItem->Action[j].nCmds;
CopyMemory(MyActions[k].CmdNum, curItem->Action[j].CmdNum,
_ctx->MyActions[_ctx->k].wTime = _ctx->curItem->Action[_ctx->j].wTime;
_ctx->MyActions[_ctx->k].perc = _ctx->curItem->Action[_ctx->j].perc;
_ctx->MyActions[_ctx->k].when = _ctx->curItem->Action[_ctx->j].when;
_ctx->MyActions[_ctx->k].nCmds = _ctx->curItem->Action[_ctx->j].nCmds;
CopyMemory(_ctx->MyActions[_ctx->k].CmdNum, _ctx->curItem->Action[_ctx->j].CmdNum,
MAX_COMMANDS_PER_ACTION * sizeof(uint16));
MyActions[k].dwLastTime = timeGetTime();
k++;
_ctx->MyActions[_ctx->k].dwLastTime = timeGetTime();
_ctx->k++;
}
}
UnlockItems();
/* La item list non ci serve piu' */
GlobalFree(il);
GlobalFree(_ctx->il);
/* Eccoci al ciclo principale. */
while (1) {
/* Cerchiamo tra tutte le idle actions quella a cui manca meno tempo per
l'esecuzione */
curTime = timeGetTime();
dwSleepTime=(uint32) - 1L;
_ctx->curTime = timeGetTime();
_ctx->dwSleepTime = (uint32)-1L;
for (k = 0;k<nIdleActions;k++)
if (curTime >= MyActions[k].dwLastTime + MyActions[k].wTime) {
dwSleepTime = 0;
for (_ctx->k = 0;_ctx->k<_ctx->nIdleActions;_ctx->k++)
if (_ctx->curTime >= _ctx->MyActions[_ctx->k].dwLastTime + _ctx->MyActions[_ctx->k].wTime) {
_ctx->dwSleepTime = 0;
break;
} else
dwSleepTime = MIN(dwSleepTime,MyActions[k].dwLastTime+MyActions[k].wTime-curTime);
_ctx->dwSleepTime = MIN(_ctx->dwSleepTime, _ctx->MyActions[_ctx->k].dwLastTime + _ctx->MyActions[_ctx->k].wTime - _ctx->curTime);
/* Ci addormentiamo, ma controllando sempre l'evento che viene settato
quando viene richiesta la nostra chiusura */
k = WaitForSingleObject(hEndPollingLocations[id], dwSleepTime);
if (k == WAIT_OBJECT_0)
_ctx->k = WaitForSingleObject(hEndPollingLocations[id], _ctx->dwSleepTime);
if (_ctx->k == WAIT_OBJECT_0)
break;
for (i = 0; i < nRealItems; i++)
if (MyThreads[i].nItem != 0) {
if (WaitForSingleObject(MyThreads[i].hThread, 0) == WAIT_OBJECT_0)
MyThreads[i].nItem = 0;
for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
if (_ctx->MyThreads[_ctx->i].nItem != 0) {
CORO_INVOKE_3(_vm->_scheduler.waitForSingleObject, _ctx->MyThreads[_ctx->i].hThread, 0, &_ctx->delayExpired);
// if result ) == WAIT_OBJECT_0)
if (!_ctx->delayExpired)
_ctx->MyThreads[_ctx->i].nItem = 0;
}
curTime = timeGetTime();
_ctx->curTime = timeGetTime();
/* Cerchiamo all'interno delle idle actions quale e' necessario eseguire */
for (k = 0; k < nIdleActions; k++)
if (curTime >= MyActions[k].dwLastTime + MyActions[k].wTime) {
MyActions[k].dwLastTime += MyActions[k].wTime;
for (_ctx->k = 0; _ctx->k < _ctx->nIdleActions; _ctx->k++)
if (_ctx->curTime >= _ctx->MyActions[_ctx->k].dwLastTime + _ctx->MyActions[_ctx->k].wTime) {
_ctx->MyActions[_ctx->k].dwLastTime += _ctx->MyActions[_ctx->k].wTime;
/* E' il momento di tirare il nostro dado virtuale, e controllare
/* E' _ctx->il momento di tirare _ctx->il nostro dado virtuale, e controllare
se la sorte e' dalla parte della idle action */
byte randomVal = (byte)_vm->_randomSource.getRandomNumber(99);
if (randomVal < MyActions[k].perc) {
if (randomVal < _ctx->MyActions[_ctx->k].perc) {
/* Controlliamo se c'e' una action in esecuzione sull'item */
if ((bExecutingAction) && (nExecutingAction == MyActions[k].nItem))
if ((bExecutingAction) && (nExecutingAction == _ctx->MyActions[_ctx->k].nItem))
continue;
/* Controlliamo se c'e' gia' un'altra idle function in esecuzione
sullo stesso item */
for (i = 0; i < nRealItems; i++)
if (MyThreads[i].nItem == MyActions[k].nItem)
for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
if (_ctx->MyThreads[_ctx->i].nItem == _ctx->MyActions[_ctx->k].nItem)
break;
if (i < nRealItems)
if (_ctx->i < _ctx->nRealItems)
continue;
/* Ok, siamo gli unici :) */
LockItems();
curItem=lpmiItems+itemGetOrderFromNum(MyActions[k].nItem);
_ctx->curItem=lpmiItems+itemGetOrderFromNum(_ctx->MyActions[_ctx->k].nItem);
/* Controlliamo se c'e' un esperessione WhenExecute */
j=MyActions[k].nAction;
if (curItem->Action[j].when != NULL)
if (!EvaluateExpression(curItem->Action[j].when)) {
_ctx->j=_ctx->MyActions[_ctx->k].nAction;
if (_ctx->curItem->Action[_ctx->j].when != NULL)
if (!EvaluateExpression(_ctx->curItem->Action[_ctx->j].when)) {
UnlockItems();
continue;
}
/* Ok, possiamo eseguire la azione. Per comodita' lo facciamo in
un nuovo thread */
newItem=(LPMPALITEM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALITEM));
if (newItem == false) {
GlobalFree(MyThreads);
GlobalFree(MyActions);
ExitThread(0);
// _endthread();
_ctx->newItem = (LPMPALITEM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALITEM));
if (_ctx->newItem == false) {
GlobalFree(_ctx->MyThreads);
GlobalFree(_ctx->MyActions);
CORO_KILL_SELF();
return;
}
CopyMemory(newItem,curItem, sizeof(MPALITEM));
CopyMemory(_ctx->newItem,_ctx->curItem, sizeof(MPALITEM));
UnlockItems();
/* Copiamo l'azione nella #0 */
// newItem->Action[0].nCmds = curItem->Action[j].nCmds;
// CopyMemory(newItem->Action[0].CmdNum,curItem->Action[j].CmdNum,newItem->Action[0].nCmds*sizeof(newItem->Action[0].CmdNum[0]));
newItem->dwRes=j;
// _ctx->newItem->Action[0].nCmds = _ctx->curItem->Action[_ctx->j].nCmds;
// CopyMemory(_ctx->newItem->Action[0].CmdNum,_ctx->curItem->Action[_ctx->j].CmdNum,_ctx->newItem->Action[0].nCmds*sizeof(_ctx->newItem->Action[0].CmdNum[0]));
_ctx->newItem->dwRes=_ctx->j;
/* Creaiamo l'action thread. Provvedera' lui a liberare la memoria
allocata per il nuovo item */
for (i = 0; i < nRealItems; i++)
if (MyThreads[i].nItem == 0)
allocata per _ctx->il nuovo item */
for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
if (_ctx->MyThreads[_ctx->i].nItem == 0)
break;
MyThreads[i].nItem=MyActions[k].nItem;
_ctx->MyThreads[_ctx->i].nItem = _ctx->MyActions[_ctx->k].nItem;
// !!! Nuova gestione dei thread
if ((MyThreads[i].hThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)ActionThread,(void *)newItem, 0, &dwId)) == NULL) {
//if ((MyThreads[i].hThread=(void*)_beginthread(ActionThread, 10240,(void *)newItem))==(void*)-1)
GlobalFree(newItem);
GlobalFree(MyThreads);
GlobalFree(MyActions);
ExitThread(0);
// _endthread();
if ((_ctx->MyThreads[_ctx->i].hThread = _vm->_scheduler.createProcess(ActionThread, &_ctx->newItem, sizeof(LPMPALITEM))) == 0) {
//if ((_ctx->MyThreads[_ctx->i].hThread=(void*)_beginthread(ActionThread, 10240,(void *)_ctx->newItem))==(void*)-1)
GlobalFree(_ctx->newItem);
GlobalFree(_ctx->MyThreads);
GlobalFree(_ctx->MyActions);
CORO_KILL_SELF();
return;
}
/* Skippa tutte le idle action dello stesso item */
@ -1251,16 +1264,16 @@ void PASCAL LocationPollThread(uint32 id) {
}
}
/* Chiude tutti i thread interni */
/* Chiude tutti _ctx->i thread interni */
/*
CODICE OBSOLETO: ANDIAMO DI SKIP CHE RULLA
for (i = 0; i < nRealItems; i++)
if (MyThreads[i].nItem != 0) {
TerminateThread(MyThreads[i].hThread, 0);
CloseHandle(MyThreads[i].hThread);
for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
if (_ctx->MyThreads[_ctx->i].nItem != 0) {
TerminateThread(_ctx->MyThreads[_ctx->i].hThread, 0);
CloseHandle(_ctx->MyThreads[_ctx->i].hThread);
}
*/
@ -1268,23 +1281,28 @@ void PASCAL LocationPollThread(uint32 id) {
// FIXME: Convert to co-routine
lplpFunctions[200](nullContext, 0, 0, 0, 0);
for (i = 0; i < nRealItems; i++)
if (MyThreads[i].nItem != 0) {
if (WaitForSingleObject(MyThreads[i].hThread,5000) != WAIT_OBJECT_0)
TerminateThread(MyThreads[i].hThread, 0);
for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
if (_ctx->MyThreads[_ctx->i].nItem != 0) {
CORO_INVOKE_3(_vm->_scheduler.waitForSingleObject, _ctx->MyThreads[_ctx->i].hThread, 5000, &_ctx->delayExpired);
CloseHandle(MyThreads[i].hThread);
/*
//if (result != WAIT_OBJECT_0)
if (_ctx->delayExpired)
TerminateThread(_ctx->MyThreads[_ctx->i].hThread, 0);
*/
_vm->_scheduler.killMatchingProcess(_ctx->MyThreads[_ctx->i].hThread);
}
// Set idle skip off
// FIXME: Convert to co-routine
lplpFunctions[201](nullContext, 0, 0, 0, 0);
CORO_INVOKE_4(lplpFunctions[201], 0, 0, 0, 0);
/* Abbiamo finito */
GlobalFree(MyThreads);
GlobalFree(MyActions);
ExitThread(1);
//endthread();
GlobalFree(_ctx->MyThreads);
GlobalFree(_ctx->MyActions);
CORO_KILL_SELF();
CORO_END_CODE;
}
@ -1516,7 +1534,7 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) {
LPMPALITEM item = lpmiItems;
int i;
LPMPALITEM newitem;
PROCESS *h;
uint32 h;
item+=ordItem;
Common::String buf = Common::String::format("Status.%u", item->nObj);
@ -1552,10 +1570,10 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) {
// 0 dell'item, e poi liberera' la memoria con la GlobalFree()
// !!! New thread management
if ((h = g_scheduler->createProcess(ActionThread, newitem)) == NULL)
if ((h = g_scheduler->createProcess(ActionThread, &newitem, sizeof(LPMPALITEM))) == NULL)
return INVALID_HANDLE_VALUE;
if ((h = g_scheduler->createProcess(ShutUpActionThread, &h->pid, sizeof(int))) == NULL)
if ((h = g_scheduler->createProcess(ShutUpActionThread, &h, sizeof(uint32))) == NULL)
return INVALID_HANDLE_VALUE;
/*
@ -2182,7 +2200,7 @@ void EXPORT mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCus) {
*
\****************************************************************************/
bool EXPORT mpalStartIdlePoll(int nLoc) {
bool mpalStartIdlePoll(int nLoc) {
uint32 i;
uint32 dwId;
@ -2196,7 +2214,7 @@ bool EXPORT mpalStartIdlePoll(int nLoc) {
hEndPollingLocations[i] = CreateEvent(NULL, true, false, NULL);
// !!! Nuova gestione dei thread
if ((PollingThreads[i] = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)LocationPollThread,(void *)i, 0, &dwId)) == NULL)
if ((PollingThreads[i] = _vm->_scheduler.createProcess(LocationPollThread, &i, sizeof(uint32))) == 0)
// if ((hEndPollingLocations[i]=(void*)_beginthread(LocationPollThread, 10240,(void *)i))==(void*)-1)
return false;
@ -2222,22 +2240,32 @@ bool EXPORT mpalStartIdlePoll(int nLoc) {
*
\****************************************************************************/
bool EXPORT mpalEndIdlePoll(int nLoc) {
uint32 i;
void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result) {
CORO_BEGIN_CONTEXT;
int i;
CORO_END_CONTEXT(_ctx);
for (i = 0; i < MAXPOLLINGLOCATIONS; i++)
if (nPollingLocations[i] == (uint32)nLoc) {
SetEvent(hEndPollingLocations[i]);
CORO_BEGIN_CODE(_ctx);
WaitForSingleObject(PollingThreads[i], INFINITE);
for (_ctx->i = 0; _ctx->i < MAXPOLLINGLOCATIONS; _ctx->i++) {
if (nPollingLocations[_ctx->i] == (uint32)nLoc) {
SetEvent(hEndPollingLocations[_ctx->i]);
CloseHandle(hEndPollingLocations[i]);
nPollingLocations[i] = 0;
CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, PollingThreads[_ctx->i], INFINITE);
return true;
CloseHandle(hEndPollingLocations[_ctx->i]);
nPollingLocations[_ctx->i] = 0;
if (result)
*result = true;
return;
}
}
return false;
if (result)
*result = false;
CORO_END_CODE;
}

View file

@ -704,8 +704,7 @@ bool EXPORT mpalStartIdlePoll(int nLoc);
*
\****************************************************************************/
bool EXPORT mpalEndIdlePoll(int nLoc);
void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result);
/****************************************************************************\

View file

@ -296,8 +296,9 @@ void Scheduler::giveWay(PPROCESS pReSchedProc) {
*
* @param pid Process identifier
* @param duration Duration in milliseconds
* @param expired Set to true if delay period expired
*/
void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration, bool *expired) {
CORO_BEGIN_CONTEXT;
uint32 endTime;
PROCESS *pProc;
@ -306,6 +307,8 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
CORO_BEGIN_CODE(_ctx);
_ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration;
if (expired)
*expired = false;
// Outer loop for doing checks until expiry
while (g_system->getMillis() < _ctx->endTime) {
@ -314,9 +317,13 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
while ((_ctx->pProc != NULL) && (_ctx->pProc->pid == pid))
_ctx->pProc = _ctx->pProc->pNext;
if (_ctx->pProc == NULL)
if (_ctx->pProc == NULL) {
// No match process found, so it's okay to break out of loop
if (expired)
*expired = true;
break;
}
// Sleep until the next cycle
CORO_SLEEP(1);
@ -333,7 +340,7 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
* @param pParam process specific info
* @param sizeParam size of process specific info
*/
PROCESS *Scheduler::createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam) {
uint32 Scheduler::createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam) {
PROCESS *pProc;
// get a free process
@ -394,7 +401,7 @@ PROCESS *Scheduler::createProcess(CORO_ADDR coroAddr, const void *pParam, int si
}
// return created process
return pProc;
return pProc->pid;
}
/**

View file

@ -111,10 +111,10 @@ public:
void rescheduleAll();
void reschedule(PPROCESS pReSchedProc = NULL);
void giveWay(PPROCESS pReSchedProc = NULL);
void waitForSingleObject(CORO_PARAM, int pid, int duration);
void waitForSingleObject(CORO_PARAM, int pid, int duration, bool *delay = NULL);
PROCESS *createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam);
PROCESS *createProcess(CORO_ADDR coroAddr, const void *pParam) {
uint32 createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam);
uint32 createProcess(CORO_ADDR coroAddr, const void *pParam) {
return createProcess(coroAddr, &pParam, sizeof(void *));
}
void killProcess(PROCESS *pKillProc);

View file

@ -59,11 +59,19 @@ namespace Tony {
bool RMTony::m_bAction = false;
uint32 RMTony::WaitEndOfAction(HANDLE hThread) {
WaitForSingleObject(hThread, INFINITE);
void RMTony::WaitEndOfAction(CORO_PARAM, const void *param) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
uint32 pid = *(const uint32 *)param;
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, pid, INFINITE);
m_bAction = false;
return 1;
CORO_END_CODE;
}
RMGfxSourceBuffer *RMTony::NewItemSpriteBuffer(int dimx, int dimy, bool bPreRLE) {
@ -205,6 +213,7 @@ void RMTony::MoveAndDoAction(RMPoint dst, RMItem *item, int nAction, int nAction
void RMTony::ExecuteAction(int nAction, int nActionItem, int nParm) {
HANDLE hThread;
uint32 pid;
if (nAction == TA_COMBINE) {
hThread = mpalQueryDoAction(TA_COMBINE, nParm, nActionItem);
@ -229,27 +238,28 @@ void RMTony::ExecuteAction(int nAction, int nActionItem, int nParm) {
}
if (hThread != INVALID_HANDLE_VALUE) {
uint32 id;
m_bAction = true;
CreateThread(NULL, 10240,(LPTHREAD_START_ROUTINE)WaitEndOfAction, (void *)hThread, 0, &id);
pid = (uint32)hThread;
_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread = hThread;
} else if (nAction != TA_GOTO) {
uint32 id;
if (nAction == TA_TALK) {
hThread = mpalQueryDoAction(6, 1, 0);
m_bAction = true;
CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)WaitEndOfAction, (void *)hThread,0,&id);
pid = (uint32)hThread;
_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread = hThread;
} else if (nAction == TA_PALESATI) {
hThread = mpalQueryDoAction(7, 1, 0);
m_bAction = true;
CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)WaitEndOfAction,(void *)hThread, 0, &id);
pid = (uint32)hThread;
_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread=hThread;
} else {
hThread = mpalQueryDoAction(5, 1, 0);
m_bAction = true;
CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)WaitEndOfAction, (void *)hThread, 0, &id);
pid = (uint32)hThread;
_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread = hThread;
}
}

View file

@ -49,6 +49,7 @@
#define TONY_TONYCHAR_H
#include "tony/mpal/stubs.h"
#include "tony/coroutine.h"
#include "tony/loc.h"
namespace Tony {
@ -128,8 +129,8 @@ protected:
// Overload dell'allocazione degli sprites per cambiare il tipo
virtual RMGfxSourceBuffer* NewItemSpriteBuffer(int dimx, int dimy, bool bPreRLE);
// Thread che aspetta la fine di un azione
static uint32 WaitEndOfAction(HANDLE hThread);
// Thread which waits for the end of an action
static void WaitEndOfAction(CORO_PARAM, const void *param);
public: // per farlo rialzare, altrimenti private
enum PATTERNS {