Browse Source

Use C++11 threading for hsEvent, and clean up the API a bit

Michael Hansen 10 years ago
parent
commit
a669abf10e
  1. 45
      Sources/Plasma/CoreLib/hsThread.h
  2. 189
      Sources/Plasma/CoreLib/hsThread_Unix.cpp
  3. 44
      Sources/Plasma/CoreLib/hsThread_Win.cpp

45
Sources/Plasma/CoreLib/hsThread.h

@ -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();
}
};
//////////////////////////////////////////////////////////////////////////////

189
Sources/Plasma/CoreLib/hsThread_Unix.cpp

@ -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;

44
Sources/Plasma/CoreLib/hsThread_Win.cpp

@ -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);

Loading…
Cancel
Save