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