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