Fast RTPS  Version 2.9.0
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#include <thread>
27extern int clock_gettime(
28 int,
29 struct timespec* tv);
30#elif _GTHREAD_USE_MUTEX_TIMEDLOCK
31#include <mutex>
32#else
33#include <pthread.h>
34#endif // if defined(_WIN32)
35
36namespace eprosima {
37namespace fastrtps {
38
39#if defined(_WIN32)
40class TimedMutex
41{
42public:
43
45 {
46 _Mtx_init(&mutex_, _Mtx_timed);
47 }
48
50 const TimedMutex&) = delete;
51 TimedMutex& operator =(
52 const TimedMutex&) = delete;
53
54 ~TimedMutex()
55 {
56 _Mtx_destroy(mutex_);
57 }
58
59 void lock()
60 {
61 _Mtx_lock(mutex_);
62 }
63
64 void unlock()
65 {
66 _Mtx_unlock(mutex_);
67 }
68
69 template <class Rep, class Period>
70 bool try_lock_for(
71 const std::chrono::duration<Rep, Period>& rel_time)
72 {
73 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
74 }
75
76 template <class Clock, class Duration>
77 bool try_lock_until(
78 const std::chrono::time_point<Clock, Duration>& abs_time)
79 {
80 std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
81
82 if (0 < nsecs.count())
83 {
84 struct timespec max_wait = {
85 0, 0
86 };
87 clock_gettime(1, &max_wait);
88 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
89 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
90 nsecs -= secs;
91 max_wait.tv_sec += secs.count();
92 max_wait.tv_nsec = (long)nsecs.count();
93 return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
94 }
95 else
96 {
97 return (_Thrd_success == _Mtx_trylock(mutex_));
98 }
99 }
100
101 void* native_handle() noexcept
102 {
103 return mutex_;
104 }
105
106private:
107
108 _Mtx_t mutex_;
109};
110
112{
113public:
114
116 {
117 _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
118 }
119
121 const TimedMutex&) = delete;
122 RecursiveTimedMutex& operator =(
123 const TimedMutex&) = delete;
124
125 ~RecursiveTimedMutex()
126 {
127 _Mtx_destroy(mutex_);
128 }
129
130 void lock()
131 {
132 _Mtx_lock(mutex_);
133 }
134
135 void unlock()
136 {
137 _Mtx_unlock(mutex_);
138 }
139
140 bool try_lock()
141 {
142 return (_Thrd_success == _Mtx_trylock(mutex_));
143 }
144
145 template <class Rep, class Period>
146 bool try_lock_for(
147 const std::chrono::duration<Rep, Period>& rel_time)
148 {
149 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
150 }
151
152 template <class Clock, class Duration>
153 bool try_lock_until(
154 const std::chrono::time_point<Clock, Duration>& abs_time)
155 {
156 std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
157 if (0 < nsecs.count())
158 {
159 struct timespec max_wait = {
160 0, 0
161 };
162 clock_gettime(1, &max_wait);
163 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
164 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
165 nsecs -= secs;
166 max_wait.tv_sec += secs.count();
167 max_wait.tv_nsec = (long)nsecs.count();
168 return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
169 }
170 else
171 {
172 return (_Thrd_success == _Mtx_trylock(mutex_));
173 }
174 }
175
176 void* native_handle() noexcept
177 {
178 return mutex_;
179 }
180
181private:
182
183 _Mtx_t mutex_;
184};
185#elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__unix__)
186using TimedMutex = std::timed_mutex;
187using RecursiveTimedMutex = std::recursive_timed_mutex;
188#else
189class TimedMutex
190{
191public:
192
193 TimedMutex()
194 {
195 pthread_mutex_init(&mutex_, nullptr);
196 }
197
199 const TimedMutex&) = delete;
200 TimedMutex& operator =(
201 const TimedMutex&) = delete;
202
204 {
205 pthread_mutex_destroy(&mutex_);
206 }
207
208 void lock()
209 {
210 pthread_mutex_lock(&mutex_);
211 }
212
213 void unlock()
214 {
215 pthread_mutex_unlock(&mutex_);
216 }
217
218 template <class Rep, class Period>
219 bool try_lock_for(
220 const std::chrono::duration<Rep, Period>& rel_time)
221 {
222 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
223 }
224
225 template <class Clock, class Duration>
226 bool try_lock_until(
227 const std::chrono::time_point<Clock, Duration>& abs_time)
228 {
229 std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
230 struct timespec max_wait = {
231 0, 0
232 };
233 clock_gettime(CLOCK_REALTIME, &max_wait);
234 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
235 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
236 nsecs -= secs;
237 max_wait.tv_sec += secs.count();
238 max_wait.tv_nsec = (long)nsecs.count();
239 return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
240 }
241
242 pthread_mutex_t* native_handle() noexcept
243 {
244 return &mutex_;
245 }
246
247private:
248
249 pthread_mutex_t mutex_;
250};
251
253{
254public:
255
257 {
258 pthread_mutexattr_init(&mutex_attr_);
259 pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE);
260 pthread_mutex_init(&mutex_, &mutex_attr_);
261 }
262
264 const RecursiveTimedMutex&) = delete;
265 RecursiveTimedMutex& operator =(
266 const RecursiveTimedMutex&) = delete;
267
268 ~RecursiveTimedMutex()
269 {
270 pthread_mutex_destroy(&mutex_);
271 pthread_mutexattr_destroy(&mutex_attr_);
272 }
273
274 void lock()
275 {
276 pthread_mutex_lock(&mutex_);
277 }
278
279 void unlock()
280 {
281 pthread_mutex_unlock(&mutex_);
282 }
283
284 bool try_lock()
285 {
286 return (0 == pthread_mutex_trylock(&mutex_));
287 }
288
289 template <class Rep, class Period>
290 bool try_lock_for(
291 const std::chrono::duration<Rep, Period>& rel_time)
292 {
293 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
294 }
295
296 template <class Clock, class Duration>
297 bool try_lock_until(
298 const std::chrono::time_point<Clock, Duration>& abs_time)
299 {
300 std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
301 struct timespec max_wait = {
302 0, 0
303 };
304 clock_gettime(CLOCK_REALTIME, &max_wait);
305 nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
306 auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
307 nsecs -= secs;
308 max_wait.tv_sec += secs.count();
309 max_wait.tv_nsec = (long)nsecs.count();
310 return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
311 }
312
313 pthread_mutex_t* native_handle() noexcept
314 {
315 return &mutex_;
316 }
317
318private:
319
320 pthread_mutexattr_t mutex_attr_;
321
322 pthread_mutex_t mutex_;
323};
324
325#endif //_WIN32
326
327} //namespace fastrtps
328} //namespace eprosima
329
330#endif // _UTILS_TIMEDMUTEX_HPP_
std::recursive_timed_mutex RecursiveTimedMutex
Definition: TimedMutex.hpp:187
std::timed_mutex TimedMutex
Definition: TimedMutex.hpp:186
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23