Robotics Library  0.7.0
condition_variable.h
Go to the documentation of this file.
1 //
2 // Copyright (c) 2009, Markus Rickert
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 //
14 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 // POSSIBILITY OF SUCH DAMAGE.
25 //
26 
27 #ifndef RL_UTIL_XENOMAI_CONDITION_VARIABLE_H
28 #define RL_UTIL_XENOMAI_CONDITION_VARIABLE_H
29 
30 #include <chrono>
31 #include <memory>
32 #include <mutex>
33 #include <native/cond.h>
34 
35 #include "chrono.h"
36 #include "mutex.h"
37 
38 namespace rl
39 {
40  namespace util
41  {
42  namespace xenomai
43  {
44  typedef recursive_mutex mutex; // TODO
45 
47  {
48  public:
49  typedef RT_COND native_type;
50 
52 
54  M_cond()
55  {
56  int e = ::rt_cond_create(&this->M_cond, nullptr);
57 
58  if (e)
59  {
60  throw ::std::system_error(::std::error_code(-e, ::std::generic_category()));
61  }
62  }
63 
65  {
66  int e = ::rt_cond_delete(&this->M_cond);
67 
68  if (e)
69  {
70  throw ::std::system_error(::std::error_code(-e, ::std::generic_category()));
71  }
72  }
73 
75 
77 
79  {
80  return &this->M_cond;
81  }
82 
83  void notify_one()
84  {
85  int e = ::rt_cond_signal(&this->M_cond);
86 
87  if (e)
88  {
89  throw ::std::system_error(::std::error_code(-e, ::std::generic_category()));
90  }
91  }
92 
93  void notify_all()
94  {
95  int e = ::rt_cond_broadcast(&this->M_cond);
96 
97  if (e)
98  {
99  throw ::std::system_error(::std::error_code(-e, ::std::generic_category()));
100  }
101  }
102 
103  void wait(::std::unique_lock<mutex>& lock)
104  {
105  int e = ::rt_cond_wait(&this->M_cond, lock.mutex()->native_handle(), TM_INFINITE);
106 
107  if (e)
108  {
109  throw ::std::system_error(::std::error_code(-e, ::std::generic_category()));
110  }
111  }
112 
113  template<typename Predicate>
114  void wait(::std::unique_lock<mutex>& lock, Predicate p)
115  {
116  while (!p())
117  {
118  this->wait(lock);
119  }
120  }
121 
122  template<typename Duration>
123  ::std::cv_status wait_until(::std::unique_lock<mutex>& lock, const ::std::chrono::time_point<clock_t, Duration>& atime)
124  {
125  ::std::chrono::time_point<clock_t, ::std::chrono::nanoseconds> ns = ::std::chrono::time_point_cast< ::std::chrono::nanoseconds>(atime);
126  int e = ::rt_cond_wait_until(&this->M_cond, lock.mutex()->native_handle(), ::rt_timer_ns2ticks(ns.time_since_epoch().count()));
127 
128  if (e)
129  {
130  throw ::std::system_error(::std::error_code(-e, ::std::generic_category()));
131  }
132 
133  return (clock_t::now() < atime ? ::std::cv_status::no_timeout : ::std::cv_status::timeout);
134  }
135 
136  template<typename Clock, typename Duration>
137  ::std::cv_status wait_until(::std::unique_lock<mutex>& lock, const ::std::chrono::time_point<Clock, Duration>& atime)
138  {
139  const typename Clock::time_point c_entry = Clock::now();
140  const clock_t::time_point s_entry = clock_t::now();
141  const ::std::chrono::nanoseconds delta = atime - c_entry;
142  const clock_t::time_point s_atime = s_entry + delta;
143  return this->wait_until(lock, s_atime);
144  }
145 
146  template<typename Clock, typename Duration, typename Predicate>
147  bool wait_until(::std::unique_lock<mutex>& lock, const ::std::chrono::time_point<Clock, Duration>& atime, Predicate p)
148  {
149  while (!p())
150  {
151  if (this->wait_until(lock, atime) == ::std::cv_status::timeout)
152  {
153  return p();
154  }
155  }
156 
157  return true;
158  }
159 
160  template<typename Rep, typename Period>
161  ::std::cv_status wait_for(::std::unique_lock<mutex>& lock, const ::std::chrono::duration<Rep, Period>& rtime)
162  {
163  return this->wait_until(lock, clock_t::now() + rtime);
164  }
165 
166  template<typename Rep, typename Period, typename Predicate>
167  bool wait_for(::std::unique_lock<mutex>& lock, const ::std::chrono::duration<Rep, Period>& rtime, Predicate p)
168  {
169  return this->wait_until(lock, clock_t::now() + rtime, ::std::move(p));
170  }
171 
172  private:
174 
176  };
177 
179  {
180  public:
182 
184  M_cond(),
185  M_mutex(std::make_shared<mutex>())
186  {
187  }
188 
190  {
191  }
192 
194 
196 
198  {
199  return this->M_cond.native_handle();
200  }
201 
202  void notify_one()
203  {
204  ::std::lock_guard<mutex> lock(*this->M_mutex);
205  this->M_cond.notify_one();
206  }
207 
208  void notify_all()
209  {
210  ::std::lock_guard<mutex> lock(*this->M_mutex);
211  this->M_cond.notify_all();
212  }
213 
214  template<typename Lock>
215  void wait(Lock& lock)
216  {
217  ::std::shared_ptr<mutex> my_mutex = this->M_mutex;
218  ::std::unique_lock<mutex> my_lock(*my_mutex);
219  Unlock<Lock> unlock(lock);
220  ::std::unique_lock<mutex> my_lock2(::std::move(my_lock));
221  this->M_cond.wait(my_lock2);
222  }
223 
224 
225  template<typename Lock, typename Predicate>
226  void wait(Lock& lock, Predicate p)
227  {
228  while (!p())
229  {
230  this->wait(lock);
231  }
232  }
233 
234  template<typename Lock, typename Clock, typename Duration>
235  ::std::cv_status wait_until(Lock& lock, const ::std::chrono::time_point<Clock, Duration>& atime)
236  {
237  ::std::shared_ptr<mutex> my_mutex = this->M_mutex;
238  ::std::unique_lock<mutex> my_lock(*my_mutex);
239  Unlock<Lock> unlock(lock);
240  ::std::unique_lock<mutex> my_lock2(::std::move(my_lock));
241  return this->M_cond.wait_until(my_lock2, atime);
242  }
243 
244  template<typename Lock, typename Clock, typename Duration, typename Predicate>
245  bool wait_until(Lock& lock, const ::std::chrono::time_point<Clock, Duration>& atime, Predicate p)
246  {
247  while (!p())
248  {
249  if (this->wait_until(lock, atime) == ::std::cv_status::timeout)
250  {
251  return p();
252  }
253  }
254 
255  return true;
256  }
257 
258  template<typename Lock, typename Rep, typename Period>
259  ::std::cv_status wait_for(Lock& lock, const ::std::chrono::duration<Rep, Period>& rtime)
260  {
261  return this->wait_until(lock, clock_t::now() + rtime);
262  }
263 
264  template<typename Lock, typename Rep, typename Period, typename Predicate>
265  bool wait_for(Lock& lock, const ::std::chrono::duration<Rep, Period>& rtime, Predicate p)
266  {
267  return this->wait_until(lock, clock_t::now() + rtime, ::std::move(p));
268  }
269 
270  protected:
271 
272  private:
273  typedef chrono::system_clock clock_t; // TODO
274 
275  template<typename Lock>
276  struct Unlock
277  {
278  explicit Unlock(Lock& lk) :
279  M_lock(lk)
280  {
281  this->lk.unlock();
282  }
283 
284  Unlock(const Unlock&) = delete;
285 
286  Unlock& operator=(const Unlock&) = delete;
287 
288  ~Unlock() noexcept(false)
289  {
290  if (::std::uncaught_exception())
291  {
292  try
293  {
294  this->M_lock.lock();
295  }
296  catch (...)
297  {
298  }
299  }
300  else
301  {
302  this->M_lock.lock();
303  }
304  }
305 
306  Lock& M_lock;
307  };
308 
310 
311  ::std::shared_ptr<mutex> M_mutex;
312  };
313  }
314  }
315 }
316 
317 #endif // RL_UTIL_XENOMAI_CONDITION_VARIABLE_H
rl::util::xenomai::recursive_mutex
Definition: mutex.h:81
rl::util::xenomai::condition_variable::notify_one
void notify_one()
Definition: condition_variable.h:83
rl::util::xenomai::condition_variable::wait
void wait(::std::unique_lock< mutex > &lock)
Definition: condition_variable.h:103
rl::util::xenomai::condition_variable_any::wait_until
::std::cv_status wait_until(Lock &lock, const ::std::chrono::time_point< Clock, Duration > &atime)
Definition: condition_variable.h:235
rl::util::xenomai::condition_variable::wait_until
bool wait_until(::std::unique_lock< mutex > &lock, const ::std::chrono::time_point< Clock, Duration > &atime, Predicate p)
Definition: condition_variable.h:147
rl::util::xenomai::chrono::system_clock
Definition: chrono.h:62
rl::util::xenomai::condition_variable_any::native_handle
native_handle_type native_handle()
Definition: condition_variable.h:197
rl::util::xenomai::condition_variable_any::wait
void wait(Lock &lock, Predicate p)
Definition: condition_variable.h:226
rl::util::xenomai::condition_variable_any::wait
void wait(Lock &lock)
Definition: condition_variable.h:215
rl::util::xenomai::condition_variable_any::wait_for
bool wait_for(Lock &lock, const ::std::chrono::duration< Rep, Period > &rtime, Predicate p)
Definition: condition_variable.h:265
rl::util::xenomai::condition_variable_any
Definition: condition_variable.h:179
rl::util::xenomai::condition_variable_any::notify_one
void notify_one()
Definition: condition_variable.h:202
rl::util::xenomai::condition_variable::clock_t
chrono::system_clock clock_t
Definition: condition_variable.h:173
rl::util::xenomai::condition_variable
Definition: condition_variable.h:47
rl::util::xenomai::condition_variable::M_cond
native_type M_cond
Definition: condition_variable.h:175
rl::util::xenomai::condition_variable::notify_all
void notify_all()
Definition: condition_variable.h:93
rl::util::xenomai::condition_variable::~condition_variable
~condition_variable()
Definition: condition_variable.h:64
rl::util::xenomai::condition_variable::wait_until
::std::cv_status wait_until(::std::unique_lock< mutex > &lock, const ::std::chrono::time_point< clock_t, Duration > &atime)
Definition: condition_variable.h:123
rl::util::xenomai::condition_variable_any::Unlock::M_lock
Lock & M_lock
Definition: condition_variable.h:306
rl::util::xenomai::condition_variable_any::condition_variable_any
condition_variable_any(const condition_variable_any &)=delete
rl::util::xenomai::condition_variable_any::wait_until
bool wait_until(Lock &lock, const ::std::chrono::time_point< Clock, Duration > &atime, Predicate p)
Definition: condition_variable.h:245
rl::util::xenomai::condition_variable::native_handle
native_handle_type native_handle()
Definition: condition_variable.h:78
rl::util::xenomai::condition_variable_any::condition_variable_any
condition_variable_any()
Definition: condition_variable.h:183
rl::util::xenomai::condition_variable_any::Unlock
Definition: condition_variable.h:277
rl::util::xenomai::condition_variable::wait_for
::std::cv_status wait_for(::std::unique_lock< mutex > &lock, const ::std::chrono::duration< Rep, Period > &rtime)
Definition: condition_variable.h:161
rl::util::xenomai::condition_variable_any::Unlock::Unlock
Unlock(const Unlock &)=delete
rl::util::xenomai::condition_variable_any::~condition_variable_any
~condition_variable_any()
Definition: condition_variable.h:189
rl::util::xenomai::condition_variable_any::wait_for
::std::cv_status wait_for(Lock &lock, const ::std::chrono::duration< Rep, Period > &rtime)
Definition: condition_variable.h:259
rl::util::xenomai::condition_variable::wait_until
::std::cv_status wait_until(::std::unique_lock< mutex > &lock, const ::std::chrono::time_point< Clock, Duration > &atime)
Definition: condition_variable.h:137
chrono.h
rl::util::xenomai::condition_variable::native_type
RT_COND native_type
Definition: condition_variable.h:49
rl::util::xenomai::mutex
recursive_mutex mutex
Definition: condition_variable.h:44
rl::util::xenomai::condition_variable::wait
void wait(::std::unique_lock< mutex > &lock, Predicate p)
Definition: condition_variable.h:114
rl::util::xenomai::condition_variable::condition_variable
condition_variable()
Definition: condition_variable.h:53
rl::util::xenomai::condition_variable_any::M_cond
condition_variable M_cond
Definition: condition_variable.h:309
rl::util::xenomai::condition_variable_any::Unlock::~Unlock
~Unlock() noexcept(false)
Definition: condition_variable.h:288
rl::util::xenomai::condition_variable_any::M_mutex
::std::shared_ptr< mutex > M_mutex
Definition: condition_variable.h:311
rl::util::xenomai::condition_variable::native_handle_type
native_type * native_handle_type
Definition: condition_variable.h:51
rl::util::xenomai::chrono::system_clock::time_point
::std::chrono::time_point< system_clock, duration > time_point
Definition: chrono.h:69
mutex.h
rl::util::xenomai::condition_variable_any::operator=
condition_variable_any & operator=(const condition_variable_any &)=delete
std
Definition: thread.h:482
rl::util::xenomai::condition_variable::condition_variable
condition_variable(const condition_variable &)=delete
rl::util::xenomai::condition_variable::wait_for
bool wait_for(::std::unique_lock< mutex > &lock, const ::std::chrono::duration< Rep, Period > &rtime, Predicate p)
Definition: condition_variable.h:167
rl::util::xenomai::condition_variable_any::Unlock::Unlock
Unlock(Lock &lk)
Definition: condition_variable.h:278
rl::util::xenomai::condition_variable::operator=
condition_variable & operator=(const condition_variable &)=delete
rl::util::xenomai::condition_variable_any::clock_t
chrono::system_clock clock_t
Definition: condition_variable.h:273
rl::util::xenomai::condition_variable_any::notify_all
void notify_all()
Definition: condition_variable.h:208
rl::util::xenomai::chrono::system_clock::now
static time_point now()
Definition: chrono.h:75
rl::util::xenomai::condition_variable_any::native_handle_type
condition_variable::native_handle_type native_handle_type
Definition: condition_variable.h:181
rl::util::xenomai::condition_variable_any::Unlock::operator=
Unlock & operator=(const Unlock &)=delete
rl
Robotics Library.
Definition: AnalogInput.cpp:30