RTAB-Map 0.23.10
Real-Time Appearance-Based Mapping
Loading...
Searching...
No Matches
USemaphore.h
1/*
2* utilite is a cross-platform library with
3* useful utilities for fast and small developing.
4* Copyright (C) 2010 Mathieu Labbe
5*
6* utilite is free library: you can redistribute it and/or modify
7* it under the terms of the GNU Lesser General Public License as published by
8* the Free Software Foundation, either version 3 of the License, or
9* (at your option) any later version.
10*
11* utilite is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU Lesser General Public License for more details.
15*
16* You should have received a copy of the GNU Lesser General Public License
17* along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20/*
21 * Originally written by Phillip Sitbon
22 * Copyright 2003
23 */
24
25#ifndef USEMAPHORE_H
26#define USEMAPHORE_H
27
28#include <errno.h>
29
30#ifdef _WIN32
31#include "rtabmap/utilite/Win32/UWin32.h"
32#include <atomic>
33#define SEM_VALUE_MAX ((int) ((~0u) >> 1))
34#else
35#include <pthread.h>
36#include <sys/time.h>
37#endif
38
56{
57public:
62 USemaphore( int initValue = 0 )
63#ifdef _WIN32
64 : _count(initValue)
65#endif
66 {
67#ifdef _WIN32
68 S = CreateSemaphore(0,initValue,SEM_VALUE_MAX,0);
69#else
70 _available = initValue;
71 pthread_mutex_init(&_waitMutex, NULL);
72 pthread_cond_init(&_cond, NULL);
73#endif
74 }
75
76 virtual ~USemaphore()
77 {
78#ifdef _WIN32
79 CloseHandle(S);
80#else
81 pthread_cond_destroy(&_cond);
82 pthread_mutex_destroy(&_waitMutex);
83#endif
84 }
85
94#ifdef _WIN32
95 bool acquire(int n = 1, int ms = 0) const
96 {
97 int rt = 0;
98 while(n-- > 0 && rt==0)
99 {
100 rt = WaitForSingleObject((HANDLE)S, ms<=0?INFINITE:ms);
101 if(rt == 0) {
102 --_count;
103 }
104 }
105 return rt == 0;
106 }
107#else
108 bool acquire(int n = 1, int ms = 0)
109 {
110 int rt = 0;
111 pthread_mutex_lock(&_waitMutex);
112 while (n > _available && rt == 0)
113 {
114 if(ms > 0)
115 {
116 struct timespec timeToWait;
117 struct timeval now;
118
119 gettimeofday(&now,NULL);
120
121 timeToWait.tv_sec = now.tv_sec + ms/1000;
122 timeToWait.tv_nsec = (now.tv_usec+1000UL*(ms%1000))*1000UL;
123
124 rt = pthread_cond_timedwait(&_cond, &_waitMutex, &timeToWait);
125 }
126 else
127 {
128 rt = pthread_cond_wait(&_cond, &_waitMutex);
129 }
130 }
131 if(rt == 0)
132 {
133 // only remove them if waiting did not fail
134 _available -= n;
135 }
136 pthread_mutex_unlock(&_waitMutex);
137 return rt == 0;
138 }
139#endif
140
141 /*
142 * Try to acquire the semaphore, not a blocking call.
143 * @return 0 if the semaphore was acquired, EAGAIN if it couldn't be taken
144 * without waiting.
145 * @note The Windows overload takes no argument (it always acquires 1).
146 */
147#ifdef _WIN32
148 int acquireTry() const
149 {
150 // Non-blocking try-acquire: timeout 0, not INFINITE. INFINITE here
151 // turned this into a blocking acquire and hung tests when the count
152 // reached 0.
153 if(WaitForSingleObject((HANDLE)S, 0) == WAIT_OBJECT_0)
154 {
155 --_count;
156 return 0;
157 }
158 return EAGAIN;
159 }
160#else
164 int acquireTry(int n)
165 {
166 pthread_mutex_lock(&_waitMutex);
167 if(n > _available)
168 {
169 pthread_mutex_unlock(&_waitMutex);
170 return EAGAIN;
171 }
172 _available -= n;
173 pthread_mutex_unlock(&_waitMutex);
174 return 0;
175 }
176#endif
177
186#ifdef _WIN32
187 int release(int n = 1) const
188 {
189 if(ReleaseSemaphore((HANDLE)S, n, 0))
190 {
191 _count += n;
192 return 0;
193 }
194 return ERANGE;
195 }
196#else
197 int release(int n = 1)
198 {
199 pthread_mutex_lock(&_waitMutex);
200 _available += n;
201 pthread_cond_broadcast(&_cond);
202 pthread_mutex_unlock(&_waitMutex);
203 return 0;
204 }
205#endif
206
211#ifdef _WIN32
212 int value() const
213 {
214 // ReleaseSemaphore(S, 0, &V) returns FALSE on Windows (release count
215 // must be >= 1) and never writes V, so we mirror the count in an atomic
216 // instead. The value is eventually-consistent under concurrent
217 // acquire/release but accurate at quiescence.
218 return (int)_count.load();
219 }
220#else
221 int value()
222 {
223 int value = 0;
224 pthread_mutex_lock(&_waitMutex);
225 value = _available;
226 pthread_mutex_unlock(&_waitMutex);
227 return value;
228 }
229#endif
230
231#ifdef _WIN32
232 /*
233 * Reset the semaphore count.
234 * @param init the initial value
235 * TODO implement on posix ?
236 */
237 void reset( int init = 0 )
238 {
239 CloseHandle(S);
240 S = CreateSemaphore(0,init,SEM_VALUE_MAX,0);
241 _count = init;
242 }
243#endif
244
245private:
246 void operator=(const USemaphore &){}
247#ifdef _WIN32
248 USemaphore(const USemaphore &S){}
249 HANDLE S;
250 mutable std::atomic<long> _count;
251#else
252 USemaphore(const USemaphore &):_available(0){}
253 pthread_mutex_t _waitMutex;
254 pthread_cond_t _cond;
255 int _available;
256#endif
257};
258
259#endif // USEMAPHORE_H
bool acquire(int n=1, int ms=0)
Definition USemaphore.h:108
int acquireTry(int n)
Definition USemaphore.h:164
int release(int n=1)
Definition USemaphore.h:197
int value()
Definition USemaphore.h:221
USemaphore(int initValue=0)
Definition USemaphore.h:62