Fast RTPS  Version 2.14.5
Fast RTPS
TimedMutex.hpp
1// Copyright 2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
19#ifndef _UTILS_TIMEDMUTEX_HPP_
20#define _UTILS_TIMEDMUTEX_HPP_
21
22#include <chrono>
23#include <iostream>
24
25#if defined(_WIN32)
26
27#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
28#include <mutex>
29#elif defined(MINGW_COMPILER)
30#include <mutex>
31#else
32#include <thread>
33extern int clock_gettime(
34 int,
35 struct timespec* tv);
36#endif // if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
37
38#elif _GTHREAD_USE_MUTEX_TIMEDLOCK
39#include <mutex>
40#else
41#include <pthread.h>
42#endif // if defined(_WIN32)
43
44namespace eprosima {
45namespace fastrtps {
46
47#if defined(_WIN32)
48
49#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
50using TimedMutex = std::timed_mutex;
51using RecursiveTimedMutex = std::recursive_timed_mutex;
52#elif defined(MINGW_COMPILER)
53using TimedMutex = std::timed_mutex;
54using RecursiveTimedMutex = std::recursive_timed_mutex;
55#else
56class TimedMutex
57{
58
59public:
60
62 {
63 _Mtx_init(&mutex_, _Mtx_timed);
64 }
65
67 const TimedMutex&) = delete;
68 TimedMutex& operator =(
69 const TimedMutex&) = delete;
70
71 ~TimedMutex()
72 {
73 _Mtx_destroy(mutex_);
74 }
75
76 void lock()
77 {
78 _Mtx_lock(mutex_);
79 }
80
81 void unlock()
82 {
83 _Mtx_unlock(mutex_);
84 }
85
86 template <class Rep, class Period>
87 bool try_lock_for(
88 const std::chrono::duration<Rep, Period>& rel_time)
89 {
90 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
91 }
92
93 template <class Clock, class Duration>
94 bool try_lock_until(
95 const std::chrono::time_point<Clock, Duration>& abs_time)
96 {
97 std::chrono::nanoseconds nsecs = abs_time - Clock::now();
98
99 if (0 < nsecs.count())
100 {
101 struct timespec max_wait = {
102 0, 0
103 };
104 clock_gettime(1, &max_wait);
105 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
106 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
107 nsecs -= secs;
108 max_wait.tv_sec += secs.count();
109 max_wait.tv_nsec = (long)nsecs.count();
110 return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
111 }
112 else
113 {
114 return (_Thrd_success == _Mtx_trylock(mutex_));
115 }
116 }
117
118 void* native_handle() noexcept
119 {
120 return mutex_;
121 }
122
123private:
124
125 _Mtx_t mutex_;
126};
127
129{
130public:
131
133 {
134 _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
135 }
136
138 const TimedMutex&) = delete;
139 RecursiveTimedMutex& operator =(
140 const TimedMutex&) = delete;
141
142 ~RecursiveTimedMutex()
143 {
144 _Mtx_destroy(mutex_);
145 }
146
147 void lock()
148 {
149 _Mtx_lock(mutex_);
150 }
151
152 void unlock()
153 {
154 _Mtx_unlock(mutex_);
155 }
156
157 bool try_lock()
158 {
159 return (_Thrd_success == _Mtx_trylock(mutex_));
160 }
161
162 template <class Rep, class Period>
163 bool try_lock_for(
164 const std::chrono::duration<Rep, Period>& rel_time)
165 {
166 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
167 }
168
169 template <class Clock, class Duration>
170 bool try_lock_until(
171 const std::chrono::time_point<Clock, Duration>& abs_time)
172 {
173 std::chrono::nanoseconds nsecs = abs_time - Clock::now();
174 if (0 < nsecs.count())
175 {
176 struct timespec max_wait = {
177 0, 0
178 };
179 clock_gettime(1, &max_wait);
180 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
181 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
182 nsecs -= secs;
183 max_wait.tv_sec += secs.count();
184 max_wait.tv_nsec = (long)nsecs.count();
185 return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
186 }
187 else
188 {
189 return (_Thrd_success == _Mtx_trylock(mutex_));
190 }
191 }
192
193 void* native_handle() noexcept
194 {
195 return mutex_;
196 }
197
198private:
199
200 _Mtx_t mutex_;
201};
202#endif // if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
203
204#elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__unix__)
205using TimedMutex = std::timed_mutex;
206using RecursiveTimedMutex = std::recursive_timed_mutex;
207#else
208class TimedMutex
209{
210public:
211
212 TimedMutex()
213 {
214 pthread_mutex_init(&mutex_, nullptr);
215 }
216
218 const TimedMutex&) = delete;
219 TimedMutex& operator =(
220 const TimedMutex&) = delete;
221
223 {
224 pthread_mutex_destroy(&mutex_);
225 }
226
227 void lock()
228 {
229 pthread_mutex_lock(&mutex_);
230 }
231
232 void unlock()
233 {
234 pthread_mutex_unlock(&mutex_);
235 }
236
237 template <class Rep, class Period>
238 bool try_lock_for(
239 const std::chrono::duration<Rep, Period>& rel_time)
240 {
241 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
242 }
243
244 template <class Clock, class Duration>
245 bool try_lock_until(
246 const std::chrono::time_point<Clock, Duration>& abs_time)
247 {
248 std::chrono::nanoseconds nsecs = abs_time - Clock::now();
249 struct timespec max_wait = {
250 0, 0
251 };
252 clock_gettime(CLOCK_REALTIME, &max_wait);
253 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
254 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
255 nsecs -= secs;
256 max_wait.tv_sec += secs.count();
257 max_wait.tv_nsec = (long)nsecs.count();
258 return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
259 }
260
261 pthread_mutex_t* native_handle() noexcept
262 {
263 return &mutex_;
264 }
265
266private:
267
268 pthread_mutex_t mutex_;
269};
270
272{
273public:
274
276 {
277 pthread_mutexattr_init(&mutex_attr_);
278 pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE);
279 pthread_mutex_init(&mutex_, &mutex_attr_);
280 }
281
283 const RecursiveTimedMutex&) = delete;
284 RecursiveTimedMutex& operator =(
285 const RecursiveTimedMutex&) = delete;
286
287 ~RecursiveTimedMutex()
288 {
289 pthread_mutex_destroy(&mutex_);
290 pthread_mutexattr_destroy(&mutex_attr_);
291 }
292
293 void lock()
294 {
295 pthread_mutex_lock(&mutex_);
296 }
297
298 void unlock()
299 {
300 pthread_mutex_unlock(&mutex_);
301 }
302
303 bool try_lock()
304 {
305 return (0 == pthread_mutex_trylock(&mutex_));
306 }
307
308 template <class Rep, class Period>
309 bool try_lock_for(
310 const std::chrono::duration<Rep, Period>& rel_time)
311 {
312 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
313 }
314
315 template <class Clock, class Duration>
316 bool try_lock_until(
317 const std::chrono::time_point<Clock, Duration>& abs_time)
318 {
319 std::chrono::nanoseconds nsecs = abs_time - Clock::now();
320 struct timespec max_wait = {
321 0, 0
322 };
323 clock_gettime(CLOCK_REALTIME, &max_wait);
324 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
325 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
326 nsecs -= secs;
327 max_wait.tv_sec += secs.count();
328 max_wait.tv_nsec = (long)nsecs.count();
329 return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
330 }
331
332 pthread_mutex_t* native_handle() noexcept
333 {
334 return &mutex_;
335 }
336
337private:
338
339 pthread_mutexattr_t mutex_attr_;
340
341 pthread_mutex_t mutex_;
342};
343
344#endif //_WIN32
345
346} //namespace fastrtps
347} //namespace eprosima
348
349#endif // _UTILS_TIMEDMUTEX_HPP_
std::recursive_timed_mutex RecursiveTimedMutex
Definition: TimedMutex.hpp:206
std::timed_mutex TimedMutex
Definition: TimedMutex.hpp:205
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23