mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-18 11:19:10 +00:00
Use C++11 threading for hsEvent, and clean up the API a bit
This commit is contained in:
@ -44,6 +44,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
|
|
||||||
#include "HeadSpin.h"
|
#include "HeadSpin.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
typedef uint32_t hsMilliseconds;
|
typedef uint32_t hsMilliseconds;
|
||||||
|
|
||||||
@ -117,49 +118,41 @@ class hsSemaphore {
|
|||||||
#else
|
#else
|
||||||
pthread_mutex_t fPMutex;
|
pthread_mutex_t fPMutex;
|
||||||
pthread_cond_t fPCond;
|
pthread_cond_t fPCond;
|
||||||
int32_t fCounter;
|
int32_t fCounter;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
hsSemaphore(int initialValue=0, const char* name=nil);
|
hsSemaphore(int initialValue=0, const char* name=nullptr);
|
||||||
~hsSemaphore();
|
~hsSemaphore();
|
||||||
|
|
||||||
#ifdef HS_BUILD_FOR_WIN32
|
#ifdef HS_BUILD_FOR_WIN32
|
||||||
HANDLE GetHandle() const { return fSemaH; }
|
HANDLE GetHandle() const { return fSemaH; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool TryWait();
|
bool Wait(hsMilliseconds timeToWait = kPosInfinity32);
|
||||||
bool Wait(hsMilliseconds timeToWait = kPosInfinity32);
|
void Signal();
|
||||||
void Signal();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
class hsEvent
|
class hsEvent
|
||||||
{
|
{
|
||||||
#if HS_BUILD_FOR_UNIX
|
std::mutex fMutex;
|
||||||
#ifndef PSEUDO_EVENT
|
std::condition_variable fCondition;
|
||||||
pthread_mutex_t fMutex;
|
|
||||||
pthread_cond_t fCond;
|
|
||||||
bool fTriggered;
|
|
||||||
#else
|
|
||||||
enum { kRead, kWrite };
|
|
||||||
int fFds[2];
|
|
||||||
std::mutex fWaitLock;
|
|
||||||
std::mutex fSignalLock;
|
|
||||||
#endif // PSEUDO_EVENT
|
|
||||||
#elif HS_BUILD_FOR_WIN32
|
|
||||||
HANDLE fEvent;
|
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
hsEvent();
|
hsEvent() { }
|
||||||
~hsEvent();
|
|
||||||
|
|
||||||
#ifdef HS_BUILD_FOR_WIN32
|
inline void Wait()
|
||||||
HANDLE GetHandle() const { return fEvent; }
|
{
|
||||||
#endif
|
std::unique_lock<std::mutex> lock(fMutex);
|
||||||
|
fCondition.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
bool Wait(hsMilliseconds timeToWait = kPosInfinity32);
|
inline void Signal()
|
||||||
void Signal();
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(fMutex);
|
||||||
|
fCondition.notify_one();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -242,21 +242,6 @@ hsSemaphore::~hsSemaphore()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hsSemaphore::TryWait()
|
|
||||||
{
|
|
||||||
#ifdef USE_SEMA
|
|
||||||
int status = ::sem_trywait(fPSema);
|
|
||||||
if (status != 0) {
|
|
||||||
return errno != EAGAIN;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
int status = ::pthread_mutex_trylock(&fPMutex);
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
return status==EBUSY ? false : true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hsSemaphore::Wait(hsMilliseconds timeToWait)
|
bool hsSemaphore::Wait(hsMilliseconds timeToWait)
|
||||||
{
|
{
|
||||||
#ifdef USE_SEMA // SHOULDN'T THIS USE timeToWait??!?!? -rje
|
#ifdef USE_SEMA // SHOULDN'T THIS USE timeToWait??!?!? -rje
|
||||||
@ -328,180 +313,6 @@ void hsSemaphore::Signal()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PSEUDO_EVENT
|
|
||||||
|
|
||||||
hsEvent::hsEvent() : fTriggered(false)
|
|
||||||
{
|
|
||||||
#ifdef EVENT_LOGGING
|
|
||||||
InitEventLoggingFile();
|
|
||||||
#endif
|
|
||||||
int status = ::pthread_mutex_init(&fMutex, nil);
|
|
||||||
hsAssert(status == 0, "hsEvent Mutex Init");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
|
|
||||||
// fCond = PTHREAD_COND_INITIALIZER;
|
|
||||||
status = ::pthread_cond_init(&fCond, nil);
|
|
||||||
hsAssert(status == 0, "hsEvent Cond Init");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
hsEvent::~hsEvent()
|
|
||||||
{
|
|
||||||
int status = ::pthread_cond_destroy(&fCond);
|
|
||||||
hsAssert(status == 0, "hsEvent Cond De-Init");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
|
|
||||||
status = ::pthread_mutex_destroy(&fMutex);
|
|
||||||
hsAssert(status == 0, "hsEvent Mutex De-Init");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hsEvent::Wait(hsMilliseconds timeToWait)
|
|
||||||
{
|
|
||||||
bool retVal = true;
|
|
||||||
int status = ::pthread_mutex_lock(&fMutex);
|
|
||||||
hsAssert(status == 0, "hsEvent Mutex Lock");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
|
|
||||||
#ifdef EVENT_LOGGING
|
|
||||||
fprintf(gEventLoggingFile,"Event: %p - In Wait (pre trig check), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( !fTriggered )
|
|
||||||
{
|
|
||||||
if (timeToWait == kPosInfinity32)
|
|
||||||
{
|
|
||||||
status = ::pthread_cond_wait(&fCond, &fMutex);
|
|
||||||
hsAssert(status == 0, "hsEvent Cond Wait");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ timespec spec;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = ::clock_gettime(CLOCK_REALTIME, &spec);
|
|
||||||
hsThrowIfFalse(result == 0);
|
|
||||||
|
|
||||||
spec.tv_sec += timeToWait / 1000;
|
|
||||||
spec.tv_nsec += (timeToWait % 1000) * 1000 * 1000;
|
|
||||||
while (spec.tv_nsec >= 1000 * 1000 * 1000)
|
|
||||||
{ spec.tv_sec += 1;
|
|
||||||
spec.tv_nsec -= 1000 * 1000 * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = ::pthread_cond_timedwait(&fCond, &fMutex, &spec);
|
|
||||||
|
|
||||||
if (status == ETIMEDOUT)
|
|
||||||
{
|
|
||||||
// It's a conditional paired with a variable!
|
|
||||||
// Pthread docs all use a variable in conjunction with the conditional
|
|
||||||
retVal = fTriggered;
|
|
||||||
status = 0;
|
|
||||||
#ifdef EVENT_LOGGING
|
|
||||||
fprintf(gEventLoggingFile,"Event: %p - In Wait (wait timed out), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef EVENT_LOGGING
|
|
||||||
fprintf(gEventLoggingFile,"Event: %p - In Wait (wait recvd signal), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
hsAssert(status == 0, "hsEvent Cond Wait");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef EVENT_LOGGING
|
|
||||||
fprintf(gEventLoggingFile,"Event: %p - In Wait (post triggerd), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fTriggered = false;
|
|
||||||
status = ::pthread_mutex_unlock(&fMutex);
|
|
||||||
hsAssert(status == 0, "hsEvent Mutex Unlock");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hsEvent::Signal()
|
|
||||||
{
|
|
||||||
int status = ::pthread_mutex_lock(&fMutex);
|
|
||||||
hsAssert(status == 0, "hsEvent Mutex Lock");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
#ifdef EVENT_LOGGING
|
|
||||||
fprintf(gEventLoggingFile,"Event: %p - In Signal, Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
|
|
||||||
#endif
|
|
||||||
fTriggered = true;
|
|
||||||
status = ::pthread_cond_broadcast(&fCond);
|
|
||||||
hsAssert(status == 0, "hsEvent Cond Broadcast");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
status = ::pthread_mutex_unlock(&fMutex);
|
|
||||||
hsAssert(status == 0, "hsEvent Mutex Unlock");
|
|
||||||
hsThrowIfOSErr(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
hsEvent::hsEvent()
|
|
||||||
{
|
|
||||||
pipe( fFds );
|
|
||||||
}
|
|
||||||
|
|
||||||
hsEvent::~hsEvent()
|
|
||||||
{
|
|
||||||
close( fFds[kRead] );
|
|
||||||
close( fFds[kWrite] );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hsEvent::Wait( hsMilliseconds timeToWait )
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(fWaitLock);
|
|
||||||
|
|
||||||
fd_set fdset;
|
|
||||||
FD_ZERO( &fdset );
|
|
||||||
FD_SET( fFds[kRead], &fdset );
|
|
||||||
|
|
||||||
int ans;
|
|
||||||
if( timeToWait==kPosInfinity32 )
|
|
||||||
{
|
|
||||||
ans = select( fFds[kRead]+1, &fdset, nil, nil, nil );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = timeToWait / 1000;
|
|
||||||
tv.tv_usec = ( timeToWait % 1000 ) * 1000;
|
|
||||||
|
|
||||||
ans = select( fFds[kRead]+1, &fdset, nil, nil, &tv );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool signaled = false;
|
|
||||||
|
|
||||||
if ( ans>0 )
|
|
||||||
{
|
|
||||||
char buf[2];
|
|
||||||
int n = read( fFds[kRead], buf, 1 );
|
|
||||||
signaled = ( n==1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
return signaled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hsEvent::Signal()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(fSignalLock);
|
|
||||||
write( fFds[kWrite], "*", 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void hsSleep::Sleep(uint32_t millis)
|
void hsSleep::Sleep(uint32_t millis)
|
||||||
{
|
{
|
||||||
uint32_t secs = millis / 1000;
|
uint32_t secs = millis / 1000;
|
||||||
|
@ -147,13 +147,6 @@ hsSemaphore::~hsSemaphore()
|
|||||||
::CloseHandle(fSemaH);
|
::CloseHandle(fSemaH);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hsSemaphore::TryWait()
|
|
||||||
{
|
|
||||||
DWORD result = ::WaitForSingleObject(fSemaH, 0);
|
|
||||||
hsAssert(result != WAIT_ABANDONED, "hsSemaphore -> Abandoned Semaphore");
|
|
||||||
return result == WAIT_OBJECT_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hsSemaphore::Wait(hsMilliseconds timeToWait)
|
bool hsSemaphore::Wait(hsMilliseconds timeToWait)
|
||||||
{
|
{
|
||||||
if (timeToWait == kPosInfinity32)
|
if (timeToWait == kPosInfinity32)
|
||||||
@ -176,43 +169,6 @@ void hsSemaphore::Signal()
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
hsEvent::hsEvent()
|
|
||||||
{
|
|
||||||
fEvent = ::CreateEvent(nil,true,false,nil);
|
|
||||||
if (fEvent == nil)
|
|
||||||
throw hsOSException(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
hsEvent::~hsEvent()
|
|
||||||
{
|
|
||||||
::CloseHandle(fEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hsEvent::Wait(hsMilliseconds timeToWait)
|
|
||||||
{
|
|
||||||
if (timeToWait == kPosInfinity32)
|
|
||||||
timeToWait = INFINITE;
|
|
||||||
|
|
||||||
DWORD result =::WaitForSingleObject(fEvent, timeToWait);
|
|
||||||
|
|
||||||
if (result == WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
::ResetEvent(fEvent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ hsThrowIfFalse(result == WAIT_TIMEOUT);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hsEvent::Signal()
|
|
||||||
{
|
|
||||||
::SetEvent(fEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void hsSleep::Sleep(uint32_t millis)
|
void hsSleep::Sleep(uint32_t millis)
|
||||||
{
|
{
|
||||||
::Sleep(millis);
|
::Sleep(millis);
|
||||||
|
Reference in New Issue
Block a user