mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Core Stop and Start: Added alternative separate thread timer/loop based waiting, instead of same thread loop waiting. You can try it with the SETUP_TIMER_WAITING option in Setup.h.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2375 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -15,7 +15,16 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Setup.h"
|
||||
#include "Thread.h"
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
#include <windows.h>
|
||||
#include "ConsoleWindow.h"
|
||||
EventCallBack FunctionPointer[10];
|
||||
#endif
|
||||
// ------------------------
|
||||
|
||||
#define THREAD_DEBUG 1
|
||||
|
||||
@ -99,9 +108,18 @@ void Thread::SetCurrentThreadAffinity(int mask)
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Regular same thread loop based waiting
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
Event::Event()
|
||||
{
|
||||
m_hEvent = 0;
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
DoneWaiting = false;
|
||||
StartWait = false;
|
||||
hTimer = NULL;
|
||||
hTimerQueue = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Event::Init()
|
||||
@ -115,22 +133,125 @@ void Event::Shutdown()
|
||||
m_hEvent = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Event::Set()
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
}
|
||||
|
||||
|
||||
void Event::Wait()
|
||||
{
|
||||
WaitForSingleObject(m_hEvent, INFINITE);
|
||||
}
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Separate thread timer based waiting, instead of same thread loop waiting. The downside with this
|
||||
is that it's less convenient to use because we can't stall any threads with a loop. The positive
|
||||
is that we don't cause these incredibly annoying WaitForEternity() hangings. */
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
/* I could not figure out how to place this in the class to, CreateTimerQueueTimer() would complain
|
||||
about some kind of type casting, anyone have any ideas about how to do it? */
|
||||
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
|
||||
{
|
||||
if (lpParam == NULL)
|
||||
{
|
||||
Console::Print("TimerRoutine lpParam is NULL\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// lpParam points to the argument; in this case it is an int
|
||||
|
||||
//Console::Print("Timer[%i] will call back\n", *(int*)lpParam);
|
||||
}
|
||||
|
||||
// Call back
|
||||
int Id = *(int*)lpParam;
|
||||
if (FunctionPointer[Id]) FunctionPointer[Id]();
|
||||
}
|
||||
|
||||
// Create a timer that will call back to the calling function
|
||||
bool Event::TimerWait(EventCallBack WaitCB, int _Id, bool OptCondition)
|
||||
{
|
||||
Id = _Id;
|
||||
|
||||
//Console::Print("TimerWait[%i]: %i %i %i\n", Id, StartWait, DoneWaiting, OptCondition);
|
||||
|
||||
FunctionPointer[Id] = WaitCB;
|
||||
|
||||
// This means we are done waiting, so we wont call back again, and we also reset the variables for this Event
|
||||
if (DoneWaiting && OptCondition)
|
||||
{
|
||||
StartWait = false;
|
||||
DoneWaiting = false;
|
||||
FunctionPointer[Id] = NULL;
|
||||
|
||||
// Delete all timers in the timer queue.
|
||||
if (!DeleteTimerQueue(hTimerQueue))
|
||||
Console::Print("DeleteTimerQueue failed (%d)\n", GetLastError());
|
||||
|
||||
hTimer = NULL;
|
||||
hTimerQueue = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Else start a new callback timer
|
||||
StartWait = true;
|
||||
|
||||
// Create the timer queue if needed
|
||||
if (!hTimerQueue)
|
||||
{
|
||||
hTimerQueue = CreateTimerQueue();
|
||||
if (NULL == hTimerQueue)
|
||||
{
|
||||
Console::Print("CreateTimerQueue failed (%d)\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set a timer to call the timer routine in 10 seconds.
|
||||
if (!CreateTimerQueueTimer( &hTimer, hTimerQueue,
|
||||
(WAITORTIMERCALLBACK)TimerRoutine, &Id , 10, 0, 0))
|
||||
{
|
||||
Console::Print("CreateTimerQueueTimer failed (%d)\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Check if we are done or not
|
||||
bool Event::DoneWait()
|
||||
{
|
||||
if (StartWait && DoneWaiting)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
// Tells the timer that we are done waiting
|
||||
void Event::SetTimer()
|
||||
{
|
||||
// We can not be done before we have started waiting
|
||||
if (StartWait) DoneWaiting = true;
|
||||
}
|
||||
#endif
|
||||
////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Supporting functions
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
@ -188,6 +309,8 @@ LONG SyncInterlockedExchange(LONG *Dest, LONG Val)
|
||||
{
|
||||
return InterlockedExchange(Dest, Val);
|
||||
}
|
||||
////////////////////////////////////////
|
||||
|
||||
|
||||
#else // !WIN32, so must be POSIX threads
|
||||
|
||||
|
Reference in New Issue
Block a user