]> git.tdb.fi Git - libs/core.git/blob - source/core/semaphore.cpp
b7151e34af517af94bffb7e04b73c64d2315bb14
[libs/core.git] / source / core / semaphore.cpp
1 /* $Id$
2
3 This file is part of libmspcore
4 Copyright © 2006  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #ifdef WIN32
9 #include <windows.h>
10 #else
11 #include <sys/time.h>
12 #include <cerrno>
13 #endif
14 #include <msp/time/timestamp.h>
15 #include <msp/time/units.h>
16 #include <msp/time/utils.h>
17 #include "mutex_private.h"
18 #include "semaphore.h"
19 #include "systemerror.h"
20
21 namespace Msp {
22
23 struct Semaphore::Private
24 {
25 #ifdef WIN32
26         HANDLE handle;
27 #else
28         Mutex mutex;
29         pthread_cond_t cond;
30         unsigned limit;
31         unsigned count;
32 #endif
33 };
34
35
36 Semaphore::Semaphore(unsigned limit):
37         priv(new Private)
38 {
39 #ifdef WIN32
40         priv->handle = CreateSemaphore(0, 0, limit, 0);
41 #else
42         pthread_cond_init(&priv->cond, 0);
43         priv->limit = limit;
44         priv->count = 0;
45 #endif
46 }
47
48 Semaphore::~Semaphore()
49 {
50 #ifdef WIN32
51         CloseHandle(priv->handle);
52 #else
53         pthread_cond_destroy(&priv->cond);
54 #endif
55         delete priv;
56 }
57
58 void Semaphore::signal()
59 {
60 #ifdef WIN32
61         if(!ReleaseSemaphore(priv->handle, 1, 0))
62                 throw system_error("Semaphore::signal");
63 #else
64         MutexLock mlock(priv->mutex);
65         if(priv->count<priv->limit)
66                 ++priv->count;
67         if(int err = pthread_cond_signal(&priv->cond))
68                 throw system_error("Semaphore::signal", err);
69 #endif
70 }
71
72 void Semaphore::wait()
73
74 #ifdef WIN32
75         DWORD ret = WaitForSingleObject(priv->handle, INFINITE);
76         if(ret==WAIT_FAILED)
77                 throw system_error("Semaphore::wait");
78 #else
79         MutexLock mlock(priv->mutex);
80         while(!priv->count)
81                 if(int err = pthread_cond_wait(&priv->cond, &priv->mutex.priv->mutex))
82                         throw system_error("Semaphore::wait", err);
83         --priv->count;
84 #endif
85 }
86
87 bool Semaphore::wait(const Time::TimeDelta &d)
88 {
89 #ifdef WIN32
90         DWORD ret = WaitForSingleObject(priv->handle, (DWORD)(d/Time::usec));
91         if(ret==WAIT_FAILED)
92                 throw system_error("Semaphore::wait");
93         return ret==WAIT_OBJECT_0;
94 #else
95         timespec timeout = Time::now()+d;
96
97         int err = pthread_cond_timedwait(&priv->cond, &priv->mutex.priv->mutex, &timeout);
98         if(err && err!=ETIMEDOUT)
99                 throw system_error("Semaphore::wait", err);
100         return err==0;
101 #endif
102 }
103
104 } // namespace Msp