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