]> git.tdb.fi Git - libs/core.git/blob - source/core/unix/semaphore.cpp
Move most platform-specific code into overlay directories
[libs/core.git] / source / core / unix / semaphore.cpp
1 #include <sys/time.h>
2 #include <cerrno>
3 #include <msp/core/systemerror.h>
4 #include <msp/time/rawtime_private.h>
5 #include <msp/time/timestamp.h>
6 #include <msp/time/utils.h>
7 #include "mutex.h"
8 #include "mutex_private.h"
9 #include "semaphore.h"
10
11 namespace Msp {
12
13 struct Semaphore::Private
14 {
15         Mutex mutex;
16         pthread_cond_t cond;
17         unsigned limit;
18         unsigned count;
19 };
20
21
22 Semaphore::Semaphore(unsigned limit):
23         priv(new Private)
24 {
25         pthread_cond_init(&priv->cond, 0);
26         priv->limit = limit;
27         priv->count = 0;
28 }
29
30 Semaphore::~Semaphore()
31 {
32         pthread_cond_destroy(&priv->cond);
33         delete priv;
34 }
35
36 void Semaphore::signal()
37 {
38         MutexLock mlock(priv->mutex);
39         if(priv->count<priv->limit)
40                 ++priv->count;
41         if(int err = pthread_cond_signal(&priv->cond))
42                 throw system_error("pthread_cond_signal", err);
43 }
44
45 void Semaphore::wait()
46
47         MutexLock mlock(priv->mutex);
48         while(!priv->count)
49                 if(int err = pthread_cond_wait(&priv->cond, &priv->mutex.priv->mutex))
50                         throw system_error("pthread_cond_wait", err);
51         --priv->count;
52 }
53
54 bool Semaphore::wait(const Time::TimeDelta &d)
55 {
56         timespec timeout = Time::rawtime_to_timespec((Time::now()+d).raw());
57
58         int err = pthread_cond_timedwait(&priv->cond, &priv->mutex.priv->mutex, &timeout);
59         if(err && err!=ETIMEDOUT)
60                 throw system_error("pthread_cond_timedwait", err);
61         return err==0;
62 }
63
64 } // namespace Msp