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>
33 extern 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 
44 namespace eprosima {
45 namespace fastrtps {
46 
47 #if defined(_WIN32)
48 
49 #if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
50 using TimedMutex = std::timed_mutex;
51 using RecursiveTimedMutex = std::recursive_timed_mutex;
52 #elif defined(MINGW_COMPILER)
53 using TimedMutex = std::timed_mutex;
54 using RecursiveTimedMutex = std::recursive_timed_mutex;
55 #else
56 class TimedMutex
57 {
58 
59 public:
60 
61  TimedMutex()
62  {
63  _Mtx_init(&mutex_, _Mtx_timed);
64  }
65 
66  TimedMutex(
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 
123 private:
124 
125  _Mtx_t mutex_;
126 };
127 
129 {
130 public:
131 
133  {
134  _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
135  }
136 
138  const TimedMutex&) = delete;
139  RecursiveTimedMutex& operator =(
140  const TimedMutex&) = delete;
141 
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 
198 private:
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__)
205 using TimedMutex = std::timed_mutex;
206 using RecursiveTimedMutex = std::recursive_timed_mutex;
207 #else
208 class TimedMutex
209 {
210 public:
211 
212  TimedMutex()
213  {
214  pthread_mutex_init(&mutex_, nullptr);
215  }
216 
217  TimedMutex(
218  const TimedMutex&) = delete;
219  TimedMutex& operator =(
220  const TimedMutex&) = delete;
221 
222  ~TimedMutex()
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 
266 private:
267 
268  pthread_mutex_t mutex_;
269 };
270 
272 {
273 public:
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 
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 
337 private:
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