]> git.tdb.fi Git - libs/core.git/blob - source/core/semaphore.cpp
New system_error exception class
[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 #ifndef WIN32
9 #include <sys/time.h>
10 #endif
11 #include <errno.h>
12 #include "semaphore.h"
13 #include "../time/timestamp.h"
14 #include "../time/units.h"
15 #include "../time/utils.h"
16
17 namespace Msp {
18
19 Semaphore::Semaphore():
20         mutex(new Mutex),
21         own_mutex(true)
22 {
23         init();
24 }
25
26 Semaphore::Semaphore(Mutex &m):
27         mutex(&m),
28         own_mutex(false)
29 {
30         init();
31 }
32
33 void Semaphore::init()
34 {
35 #ifdef WIN32
36         count = 0;
37         sem = CreateSemaphore(0, 0, 32, 0);
38 #else
39         pthread_cond_init(&sem, 0);
40 #endif
41 }
42
43 Semaphore::~Semaphore()
44 {
45         if(own_mutex)
46                 delete mutex;
47 #ifdef WIN32
48         CloseHandle(sem);
49 #else
50         pthread_cond_destroy(&sem);
51 #endif
52 }
53
54 #ifdef WIN32
55 int Semaphore::signal()
56 {
57         if(count==0) 
58                 return 0;
59
60         int ret = !ReleaseSemaphore(sem, 1, 0); 
61
62         unsigned old_count = count;
63         mutex->unlock();
64         while(count==old_count)
65                 Sleep(0);
66         mutex->lock();
67
68         return ret;
69 }
70
71 int Semaphore::broadcast()
72 {
73         if(count==0)
74                 return 0;
75         int ret = !ReleaseSemaphore(sem, count, 0);
76
77         mutex->unlock();
78         while(count)
79                 Sleep(0);
80         mutex->lock();
81
82         return ret;
83 }
84
85 int Semaphore::wait()
86
87         ++count; 
88         mutex->unlock();
89         DWORD ret = WaitForSingleObject(sem, INFINITE); 
90         mutex->lock();
91         --count;
92         
93         return ret==WAIT_OBJECT_0;
94 }
95 #endif
96
97 int Semaphore::wait(const Time::TimeDelta &d)
98 {
99 #ifndef WIN32
100         Time::TimeStamp ts = Time::now()+d;
101
102         timespec timeout;
103         timeout.tv_sec = ts.raw()/1000000;
104         timeout.tv_nsec = (ts.raw()%1000000)*1000;
105
106         int r = pthread_cond_timedwait(&sem, &mutex->mutex, &timeout);
107         if(r==ETIMEDOUT)
108                 return 1;
109         else if(r)
110                 return -1;
111         return 0;
112 #else
113         ++count;
114         mutex->lock();
115         DWORD ret = WaitForSingleObject(sem, (DWORD)(d/Time::usec));
116         mutex->unlock();
117         --count;
118         return ret==WAIT_OBJECT_0;
119 #endif
120 }
121
122 } // namespace Msp