Fast RTPS  Version 2.3.4
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  template <class Rep, class Period>
141  bool try_lock_for(
142  const std::chrono::duration<Rep, Period>& rel_time)
143  {
144  return try_lock_until(std::chrono::steady_clock::now() + rel_time);
145  }
146 
147  template <class Clock, class Duration>
148  bool try_lock_until(
149  const std::chrono::time_point<Clock, Duration>& abs_time)
150  {
151  std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
152  if (0 < nsecs.count())
153  {
154  struct timespec max_wait = {
155  0, 0
156  };
157  clock_gettime(1, &max_wait);
158  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
159  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
160  nsecs -= secs;
161  max_wait.tv_sec += secs.count();
162  max_wait.tv_nsec = (long)nsecs.count();
163  return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
164  }
165  else
166  {
167  return (_Thrd_success == _Mtx_trylock(mutex_));
168  }
169  }
170 
171  void* native_handle() noexcept
172  {
173  return mutex_;
174  }
175 
176 private:
177 
178  _Mtx_t mutex_;
179 };
180 #elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__linux__)
181 using TimedMutex = std::timed_mutex;
182 using RecursiveTimedMutex = std::recursive_timed_mutex;
183 #else
184 class TimedMutex
185 {
186 public:
187 
188  TimedMutex()
189  {
190  pthread_mutex_init(&mutex_, nullptr);
191  }
192 
193  TimedMutex(
194  const TimedMutex&) = delete;
195  TimedMutex& operator =(
196  const TimedMutex&) = delete;
197 
198  ~TimedMutex()
199  {
200  pthread_mutex_destroy(&mutex_);
201  }
202 
203  void lock()
204  {
205  pthread_mutex_lock(&mutex_);
206  }
207 
208  void unlock()
209  {
210  pthread_mutex_unlock(&mutex_);
211  }
212 
213  template <class Rep, class Period>
214  bool try_lock_for(
215  const std::chrono::duration<Rep, Period>& rel_time)
216  {
217  return try_lock_until(std::chrono::steady_clock::now() + rel_time);
218  }
219 
220  template <class Clock, class Duration>
221  bool try_lock_until(
222  const std::chrono::time_point<Clock, Duration>& abs_time)
223  {
224  std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
225  struct timespec max_wait = {
226  0, 0
227  };
228  clock_gettime(CLOCK_REALTIME, &max_wait);
229  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
230  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
231  nsecs -= secs;
232  max_wait.tv_sec += secs.count();
233  max_wait.tv_nsec = (long)nsecs.count();
234  return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
235  }
236 
237  pthread_mutex_t* native_handle() noexcept
238  {
239  return &mutex_;
240  }
241 
242 private:
243 
244  pthread_mutex_t mutex_;
245 };
246 
248 {
249 public:
250 
252  {
253  pthread_mutexattr_init(&mutex_attr_);
254  pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE);
255  pthread_mutex_init(&mutex_, &mutex_attr_);
256  }
257 
259  const RecursiveTimedMutex&) = delete;
260  RecursiveTimedMutex& operator =(
261  const RecursiveTimedMutex&) = delete;
262 
264  {
265  pthread_mutex_destroy(&mutex_);
266  pthread_mutexattr_destroy(&mutex_attr_);
267  }
268 
269  void lock()
270  {
271  pthread_mutex_lock(&mutex_);
272  }
273 
274  void unlock()
275  {
276  pthread_mutex_unlock(&mutex_);
277  }
278 
279  template <class Rep, class Period>
280  bool try_lock_for(
281  const std::chrono::duration<Rep, Period>& rel_time)
282  {
283  return try_lock_until(std::chrono::steady_clock::now() + rel_time);
284  }
285 
286  template <class Clock, class Duration>
287  bool try_lock_until(
288  const std::chrono::time_point<Clock, Duration>& abs_time)
289  {
290  std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
291  struct timespec max_wait = {
292  0, 0
293  };
294  clock_gettime(CLOCK_REALTIME, &max_wait);
295  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
296  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
297  nsecs -= secs;
298  max_wait.tv_sec += secs.count();
299  max_wait.tv_nsec = (long)nsecs.count();
300  return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
301  }
302 
303  pthread_mutex_t* native_handle() noexcept
304  {
305  return &mutex_;
306  }
307 
308 private:
309 
310  pthread_mutexattr_t mutex_attr_;
311 
312  pthread_mutex_t mutex_;
313 };
314 
315 #endif //_WIN32
316 
317 } //namespace fastrtps
318 } //namespace eprosima
319 
320 #endif // _UTILS_TIMEDMUTEX_HPP_
std::recursive_timed_mutex RecursiveTimedMutex
Definition: TimedMutex.hpp:182
std::timed_mutex TimedMutex
Definition: TimedMutex.hpp:181
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23