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 <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
typedef uint32_t hsMilliseconds;
|
||||
|
||||
@ -117,49 +118,41 @@ class hsSemaphore {
|
||||
#else
|
||||
pthread_mutex_t fPMutex;
|
||||
pthread_cond_t fPCond;
|
||||
int32_t fCounter;
|
||||
int32_t fCounter;
|
||||
#endif
|
||||
#endif
|
||||
public:
|
||||
hsSemaphore(int initialValue=0, const char* name=nil);
|
||||
hsSemaphore(int initialValue=0, const char* name=nullptr);
|
||||
~hsSemaphore();
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
HANDLE GetHandle() const { return fSemaH; }
|
||||
#endif
|
||||
|
||||
bool TryWait();
|
||||
bool Wait(hsMilliseconds timeToWait = kPosInfinity32);
|
||||
void Signal();
|
||||
bool Wait(hsMilliseconds timeToWait = kPosInfinity32);
|
||||
void Signal();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
class hsEvent
|
||||
{
|
||||
#if HS_BUILD_FOR_UNIX
|
||||
#ifndef PSEUDO_EVENT
|
||||
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
|
||||
std::mutex fMutex;
|
||||
std::condition_variable fCondition;
|
||||
|
||||
public:
|
||||
hsEvent();
|
||||
~hsEvent();
|
||||
hsEvent() { }
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
HANDLE GetHandle() const { return fEvent; }
|
||||
#endif
|
||||
inline void Wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMutex);
|
||||
fCondition.wait(lock);
|
||||
}
|
||||
|
||||
bool Wait(hsMilliseconds timeToWait = kPosInfinity32);
|
||||
void Signal();
|
||||
inline void Signal()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(fMutex);
|
||||
fCondition.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -242,21 +242,6 @@ hsSemaphore::~hsSemaphore()
|
||||
#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)
|
||||
{
|
||||
#ifdef USE_SEMA // SHOULDN'T THIS USE timeToWait??!?!? -rje
|
||||
@ -328,180 +313,6 @@ void hsSemaphore::Signal()
|
||||
#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)
|
||||
{
|
||||
uint32_t secs = millis / 1000;
|
||||
|
@ -147,13 +147,6 @@ hsSemaphore::~hsSemaphore()
|
||||
::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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
::Sleep(millis);
|
||||
|
Reference in New Issue
Block a user