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