Fast RTPS  Version 2.1.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
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(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 = { 0, 0 };
85  clock_gettime(1, &max_wait);
86  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
87  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
88  nsecs -= secs;
89  max_wait.tv_sec += secs.count();
90  max_wait.tv_nsec = (long)nsecs.count();
91  return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
92  }
93  else
94  {
95  return (_Thrd_success == _Mtx_trylock(mutex_));
96  }
97  }
98 
99  void* native_handle() noexcept
100  {
101  return mutex_;
102  }
103 
104 private:
105 
106  _Mtx_t mutex_;
107 };
108 
110 {
111 public:
112 
114  {
115  _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
116  }
117 
119  const TimedMutex&) = delete;
120  RecursiveTimedMutex& operator =(
121  const TimedMutex&) = delete;
122 
124  {
125  _Mtx_destroy(mutex_);
126  }
127 
128  void lock()
129  {
130  _Mtx_lock(mutex_);
131  }
132 
133  void unlock()
134  {
135  _Mtx_unlock(mutex_);
136  }
137 
138  template <class Rep, class Period>
139  bool try_lock_for(
140  const std::chrono::duration<Rep, Period>& rel_time)
141  {
142  return try_lock_until(chrono::steady_clock::now() + rel_time);
143  }
144 
145  template <class Clock, class Duration>
146  bool try_lock_until(
147  const std::chrono::time_point<Clock, Duration>& abs_time)
148  {
149  std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
150  if (0 < nsecs.count())
151  {
152  struct timespec max_wait = { 0, 0 };
153  clock_gettime(1, &max_wait);
154  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
155  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
156  nsecs -= secs;
157  max_wait.tv_sec += secs.count();
158  max_wait.tv_nsec = (long)nsecs.count();
159  return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
160  }
161  else
162  {
163  return (_Thrd_success == _Mtx_trylock(mutex_));
164  }
165  }
166 
167  void* native_handle() noexcept
168  {
169  return mutex_;
170  }
171 
172 private:
173 
174  _Mtx_t mutex_;
175 };
176 #elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__linux__)
177 using TimedMutex = std::timed_mutex;
178 using RecursiveTimedMutex = std::recursive_timed_mutex;
179 #else
180 class TimedMutex
181 {
182 public:
183 
184  TimedMutex()
185  {
186  pthread_mutex_init(&mutex_, nullptr);
187  }
188 
189  TimedMutex(
190  const TimedMutex&) = delete;
191  TimedMutex& operator =(
192  const TimedMutex&) = delete;
193 
194  ~TimedMutex()
195  {
196  pthread_mutex_destroy(&mutex_);
197  }
198 
199  void lock()
200  {
201  pthread_mutex_lock(&mutex_);
202  }
203 
204  void unlock()
205  {
206  pthread_mutex_unlock(&mutex_);
207  }
208 
209  template <class Rep, class Period>
210  bool try_lock_for(
211  const std::chrono::duration<Rep, Period>& rel_time)
212  {
213  return try_lock_until(std::chrono::steady_clock::now() + rel_time);
214  }
215 
216  template <class Clock, class Duration>
217  bool try_lock_until(
218  const std::chrono::time_point<Clock, Duration>& abs_time)
219  {
220  std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
221  struct timespec max_wait = { 0, 0 };
222  clock_gettime(CLOCK_REALTIME, &max_wait);
223  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
224  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
225  nsecs -= secs;
226  max_wait.tv_sec += secs.count();
227  max_wait.tv_nsec = (long)nsecs.count();
228  return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
229  }
230 
231  pthread_mutex_t* native_handle() noexcept
232  {
233  return &mutex_;
234  }
235 
236 private:
237 
238  pthread_mutex_t mutex_;
239 };
240 
242 {
243 public:
244 
246  {
247  pthread_mutexattr_init(&mutex_attr_);
248  pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE);
249  pthread_mutex_init(&mutex_, &mutex_attr_);
250  }
251 
253  const RecursiveTimedMutex&) = delete;
254  RecursiveTimedMutex& operator =(
255  const RecursiveTimedMutex&) = delete;
256 
258  {
259  pthread_mutex_destroy(&mutex_);
260  pthread_mutexattr_destroy(&mutex_attr_);
261  }
262 
263  void lock()
264  {
265  pthread_mutex_lock(&mutex_);
266  }
267 
268  void unlock()
269  {
270  pthread_mutex_unlock(&mutex_);
271  }
272 
273  template <class Rep, class Period>
274  bool try_lock_for(
275  const std::chrono::duration<Rep, Period>& rel_time)
276  {
277  return try_lock_until(std::chrono::steady_clock::now() + rel_time);
278  }
279 
280  template <class Clock, class Duration>
281  bool try_lock_until(
282  const std::chrono::time_point<Clock, Duration>& abs_time)
283  {
284  std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
285  struct timespec max_wait = { 0, 0 };
286  clock_gettime(CLOCK_REALTIME, &max_wait);
287  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
288  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
289  nsecs -= secs;
290  max_wait.tv_sec += secs.count();
291  max_wait.tv_nsec = (long)nsecs.count();
292  return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
293  }
294 
295  pthread_mutex_t* native_handle() noexcept
296  {
297  return &mutex_;
298  }
299 
300 private:
301 
302  pthread_mutexattr_t mutex_attr_;
303 
304  pthread_mutex_t mutex_;
305 };
306 
307 #endif //_WIN32
308 
309 } //namespace fastrtps
310 } //namespace eprosima
311 
312 #endif // _UTILS_TIMEDMUTEX_HPP_
eprosima::fastrtps::RecursiveTimedMutex
std::recursive_timed_mutex RecursiveTimedMutex
Definition: TimedMutex.hpp:178
eprosima::fastrtps::TimedMutex
std::timed_mutex TimedMutex
Definition: TimedMutex.hpp:177
eprosima
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23