ardour
semaphore.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012 Paul Davis
3  Author: David Robillard
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #ifndef __pbd_semaphore_h__
21 #define __pbd_semaphore_h__
22 
23 #ifdef __APPLE__
24 # include <mach/mach.h>
25 #elif defined(PLATFORM_WINDOWS)
26 # include <windows.h>
27 #ifndef INFINITE
28 #define INFINITE 0xffffffffL
29 #endif
30 #else
31 # include <semaphore.h>
32 # include <errno.h>
33 #endif
34 
35 #include "pbd/libpbd_visibility.h"
36 #include "pbd/failed_constructor.h"
37 
38 namespace PBD {
39 
52 class /*LIBPBD_API*/ Semaphore
53 {
54 public:
60  inline Semaphore(unsigned initial);
61 
62  inline ~Semaphore();
63 
65  inline void post();
66 
68  inline bool wait();
69 
71  inline bool try_wait();
72 
73 private:
74 #if defined(__APPLE__)
75  semaphore_t _sem; // sem_t is a worthless broken mess on OSX
76 #elif defined(PLATFORM_WINDOWS)
77  HANDLE _sem; // types are overrated anyway
78 #else
79  sem_t _sem;
80 #endif
81 };
82 
83 #ifdef __APPLE__
84 
85 inline
86 Semaphore::Semaphore(unsigned initial)
87 {
88  if (semaphore_create(mach_task_self(), &_sem, SYNC_POLICY_FIFO, initial)) {
89  throw failed_constructor();
90  }
91 }
92 
93 inline
95 {
96  semaphore_destroy(mach_task_self(), _sem);
97 }
98 
99 inline void
101 {
102  semaphore_signal(_sem);
103 }
104 
105 inline bool
107 {
108  if (semaphore_wait(_sem) != KERN_SUCCESS) {
109  return false;
110  }
111  return true;
112 }
113 
114 inline bool
116 {
117  const mach_timespec_t zero = { 0, 0 };
118  return semaphore_timedwait(_sem, zero) == KERN_SUCCESS;
119 }
120 
121 #elif defined(PLATFORM_WINDOWS)
122 
123 inline
124 Semaphore::Semaphore(unsigned initial)
125 {
126  if (!(_sem = CreateSemaphore(NULL, initial, LONG_MAX, NULL))) {
127  throw failed_constructor();
128  }
129 }
130 
131 inline
133 {
134  CloseHandle(_sem);
135 }
136 
137 inline void
139 {
140  ReleaseSemaphore(_sem, 1, NULL);
141 }
142 
143 inline bool
145 {
146  if (WaitForSingleObject(_sem, INFINITE) != WAIT_OBJECT_0) {
147  return false;
148  }
149  return true;
150 }
151 
152 inline bool
154 {
155  return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
156 }
157 
158 #else /* !defined(__APPLE__) && !defined(PLATFORM_WINDOWS) */
159 
160 Semaphore::Semaphore(unsigned initial)
161 {
162  if (sem_init(&_sem, 0, initial)) {
163  throw failed_constructor();
164  }
165 }
166 
167 inline
169 {
170  sem_destroy(&_sem);
171 }
172 
173 inline void
175 {
176  sem_post(&_sem);
177 }
178 
179 inline bool
181 {
182  while (sem_wait(&_sem)) {
183  if (errno != EINTR) {
184  return false; // We are all doomed
185  }
186  /* Otherwise, interrupted (rare/weird), so try again. */
187  }
188 
189  return true;
190 }
191 
192 inline bool
194 {
195  return (sem_trywait(&_sem) == 0);
196 }
197 
198 #endif
199 
200 } // namespace PBD
201 
202 #endif /* __pbd_semaphore_h__ */
bool try_wait()
Definition: semaphore.h:193
Definition: debug.h:30
Semaphore(unsigned initial)
Definition: semaphore.h:160