Fast RTPS  Version 2.4.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>
27 extern 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 
36 namespace eprosima {
37 namespace fastrtps {
38 
39 #if defined(_WIN32)
40 class TimedMutex
41 {
42 public:
43 
44  TimedMutex()
45  {
46  _Mtx_init(&mutex_, _Mtx_timed);
47  }
48 
49  TimedMutex(
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 
106 private:
107 
108  _Mtx_t mutex_;
109 };
110 
112 {
113 public:
114 
116  {
117  _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
118  }
119 
121  const TimedMutex&) = delete;
122  RecursiveTimedMutex& operator =(
123  const TimedMutex&) = delete;
124 
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 
181 private:
182 
183  _Mtx_t mutex_;
184 };
185 #elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__unix__)
186 using TimedMutex = std::timed_mutex;
187 using RecursiveTimedMutex = std::recursive_timed_mutex;
188 #else
189 class TimedMutex
190 {
191 public:
192 
193  TimedMutex()
194  {
195  pthread_mutex_init(&mutex_, nullptr);
196  }
197 
198  TimedMutex(
199  const TimedMutex&) = delete;
200  TimedMutex& operator =(
201  const TimedMutex&) = delete;
202 
203  ~TimedMutex()
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 
247 private:
248 
249  pthread_mutex_t mutex_;
250 };
251 
253 {
254 public:
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 
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 
318 private:
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