X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fcore%2Fsemaphore.cpp;h=8fa1be90f7c7e234abde3e74409bfb916acbffb9;hp=139cae2f4ca523ffac47af9487663799a65c17ea;hb=03bacb2343eb5d17819732582c0866f087e9ce27;hpb=b56eb5ec1da675da0c66abc53c1e4f6c4e4cccbd diff --git a/source/core/semaphore.cpp b/source/core/semaphore.cpp index 139cae2..8fa1be9 100644 --- a/source/core/semaphore.cpp +++ b/source/core/semaphore.cpp @@ -1,121 +1,97 @@ -/* $Id$ - -This file is part of libmspcore -Copyright © 2006 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - -#ifndef WIN32 +#ifdef WIN32 +#include +#else #include +#include #endif -#include +#include +#include +#include +#include +#include "mutex_private.h" #include "semaphore.h" -#include "../time/timestamp.h" -#include "../time/units.h" -#include "../time/utils.h" +#include "systemerror.h" namespace Msp { -Semaphore::Semaphore(): - mutex(new Mutex), - own_mutex(true) +struct Semaphore::Private { - init(); -} +#ifdef WIN32 + HANDLE handle; +#else + Mutex mutex; + pthread_cond_t cond; + unsigned limit; + unsigned count; +#endif +}; -Semaphore::Semaphore(Mutex &m): - mutex(&m), - own_mutex(false) -{ - init(); -} -void Semaphore::init() +Semaphore::Semaphore(unsigned limit): + priv(new Private) { #ifdef WIN32 - count = 0; - sem = CreateSemaphore(0, 0, 32, 0); + priv->handle = CreateSemaphore(0, 0, limit, 0); #else - pthread_cond_init(&sem, 0); + pthread_cond_init(&priv->cond, 0); + priv->limit = limit; + priv->count = 0; #endif } Semaphore::~Semaphore() { - if(own_mutex) - delete mutex; #ifdef WIN32 - CloseHandle(sem); + CloseHandle(priv->handle); #else - pthread_cond_destroy(&sem); + pthread_cond_destroy(&priv->cond); #endif + delete priv; } -#ifdef WIN32 -int Semaphore::signal() -{ - if(count==0) - return 0; - - int ret = !ReleaseSemaphore(sem, 1, 0); - - unsigned old_count = count; - mutex->unlock(); - while(count==old_count) - Sleep(0); - mutex->lock(); - - return ret; -} - -int Semaphore::broadcast() +void Semaphore::signal() { - if(count==0) - return 0; - int ret = !ReleaseSemaphore(sem, count, 0); - - mutex->unlock(); - while(count) - Sleep(0); - mutex->lock(); - - return ret; +#ifdef WIN32 + if(!ReleaseSemaphore(priv->handle, 1, 0)) + throw system_error("Semaphore::signal"); +#else + MutexLock mlock(priv->mutex); + if(priv->countlimit) + ++priv->count; + if(int err = pthread_cond_signal(&priv->cond)) + throw system_error("Semaphore::signal", err); +#endif } -int Semaphore::wait() +void Semaphore::wait() { - ++count; - mutex->unlock(); - DWORD ret = WaitForSingleObject(sem, INFINITE); - mutex->lock(); - --count; - - return ret==WAIT_OBJECT_0; -} +#ifdef WIN32 + DWORD ret = WaitForSingleObject(priv->handle, INFINITE); + if(ret==WAIT_FAILED) + throw system_error("Semaphore::wait"); +#else + MutexLock mlock(priv->mutex); + while(!priv->count) + if(int err = pthread_cond_wait(&priv->cond, &priv->mutex.priv->mutex)) + throw system_error("Semaphore::wait", err); + --priv->count; #endif +} -int Semaphore::wait(const Time::TimeDelta &d) +bool Semaphore::wait(const Time::TimeDelta &d) { -#ifndef WIN32 - Time::TimeStamp ts = Time::now()+d; - - timespec timeout; - timeout.tv_sec = ts.raw()/1000000; - timeout.tv_nsec = (ts.raw()%1000000)*1000; - - int r = pthread_cond_timedwait(&sem, &mutex->mutex, &timeout); - if(r==ETIMEDOUT) - return 1; - else if(r) - return -1; - return 0; -#else - ++count; - mutex->lock(); - DWORD ret = WaitForSingleObject(sem, (DWORD)(d/Time::usec)); - mutex->unlock(); - --count; +#ifdef WIN32 + DWORD ret = WaitForSingleObject(priv->handle, (DWORD)(d/Time::usec)); + if(ret==WAIT_FAILED) + throw system_error("Semaphore::wait"); return ret==WAIT_OBJECT_0; +#else + timespec timeout = Time::rawtime_to_timespec((Time::now()+d).raw()); + + int err = pthread_cond_timedwait(&priv->cond, &priv->mutex.priv->mutex, &timeout); + if(err && err!=ETIMEDOUT) + throw system_error("Semaphore::wait", err); + return err==0; #endif }