X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcore%2Fsemaphore.cpp;h=544fb27f81b192731f4175b97257f7b6e534268c;hb=a1d6fa071280123f282c1bac3b68008672401024;hp=7006eafc51ae5e8c43d938c9f8d04824fbc5e03c;hpb=ff52b5032a3f040de5d3a48f953f2943d7a223b3;p=libs%2Fcore.git diff --git a/source/core/semaphore.cpp b/source/core/semaphore.cpp index 7006eaf..544fb27 100644 --- a/source/core/semaphore.cpp +++ b/source/core/semaphore.cpp @@ -1,35 +1,107 @@ -/* -This file is part of libmspframework +/* $Id$ + +This file is part of libmspcore Copyright © 2006 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ + +#ifdef WIN32 +#include +#else #include -#include +#include +#endif +#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 { -int Semaphore::wait(const Time::TimeDelta &d) +struct Semaphore::Private { -#ifndef WIN32 - Time::TimeStamp ts=Time::now()+d; +#ifdef WIN32 + HANDLE handle; +#else + Mutex mutex; + pthread_cond_t cond; + unsigned limit; + unsigned count; +#endif +}; - timespec timeout; - timeout.tv_sec=ts.raw()/1000000; - timeout.tv_nsec=(ts.raw()%1000000)*1000; - - MutexLock l(mutex); - int r=pthread_cond_timedwait(&sem, &mutex.mutex, &timeout); - if(r==ETIMEDOUT) - return 1; - else if(r) - return -1; - return 0; + +Semaphore::Semaphore(unsigned limit): + priv(new Private) +{ +#ifdef WIN32 + priv->handle = CreateSemaphore(0, 0, limit, 0); +#else + pthread_cond_init(&priv->cond, 0); + priv->limit = limit; + priv->count = 0; +#endif +} + +Semaphore::~Semaphore() +{ +#ifdef WIN32 + CloseHandle(priv->handle); #else - return WaitForSingleObject(sem, (DWORD)(d/Time::usec))==WAIT_OBJECT_0; + pthread_cond_destroy(&priv->cond); +#endif + delete priv; +} + +void Semaphore::signal() +{ +#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 +} + +void Semaphore::wait() +{ +#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 +} + +bool Semaphore::wait(const Time::TimeDelta &d) +{ +#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 + Time::TimeStamp ts = Time::now()+d; + + timespec timeout; + timeout.tv_sec = ts.raw()/1000000; + timeout.tv_nsec = (ts.raw()%1000000)*1000; + + 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 }