Fast RTPS  Version 2.4.1
Fast RTPS
TimedConditionVariable.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_TIMEDCONDITIONVARIABLE_HPP_
20 #define _UTILS_TIMEDCONDITIONVARIABLE_HPP_
21 #include <fastrtps/config.h>
22 
23 /*
24  NOTE: Windows implementation temporary disabled due to aleatory high CPU consumption when
25  calling _Cnd_timedwait function, making some tests to fail and very poor performance.
26  Related task: #6274
27 
28  #if HAVE_STRICT_REALTIME && defined(_WIN32)
29  #include <thr/xthreads.h>
30 
31  #define CLOCK_REALTIME 0
32  #define CV_INIT_(x) _Cnd_init(x)
33  #define CV_WAIT_(cv, x) _Cnd_wait(cv, (_Mtx_t)x)
34  #define CV_TIMEDWAIT_(cv, x, y) _Cnd_timedwait(cv, (_Mtx_t)x, (xtime*)y)
35  #define CV_SIGNAL_(cv) _Cnd_signal(cv)
36  #define CV_BROADCAST_(cv) _Cnd_broadcast(cv)
37  #define CV_T_ _Cnd_t
38 
39  extern int clock_gettime(int, struct timespec* tv);
40  #elif HAVE_STRICT_REALTIME && defined(__unix__)
41  */
42 #if HAVE_STRICT_REALTIME && defined(__unix__)
43 #include <pthread.h>
44 
45 #define CV_INIT_(x) pthread_cond_init(x, NULL);
46 #define CV_WAIT_(cv, x) pthread_cond_wait(&cv, x)
47 #define CV_TIMEDWAIT_(cv, x, y) pthread_cond_timedwait(&cv, x, y)
48 #define CV_SIGNAL_(cv) pthread_cond_signal(&cv)
49 #define CV_BROADCAST_(cv) pthread_cond_broadcast(&cv)
50 #define CV_T_ pthread_cond_t
51 #else
52 #include <condition_variable>
53 #endif // if HAVE_STRICT_REALTIME && defined(__unix__)
54 
55 #include <mutex>
56 #include <chrono>
57 #include <functional>
58 
59 namespace eprosima {
60 namespace fastrtps {
61 
62 #if HAVE_STRICT_REALTIME && (/*defined(_WIN32) ||*/ defined(__unix__))
63 
65 {
66 public:
67 
69  {
70  CV_INIT_(&cv_);
71  }
72 
73  template<typename Mutex>
74  void wait(
75  std::unique_lock<Mutex>& lock,
76  std::function<bool()> predicate)
77  {
78  while (!predicate())
79  {
80  CV_WAIT_(cv_, lock.mutex()->native_handle());
81  }
82  }
83 
84  template<typename Mutex>
85  void wait(
86  std::unique_lock<Mutex>& lock)
87  {
88  CV_WAIT_(cv_, lock.mutex()->native_handle());
89  }
90 
91  template<typename Mutex>
92  bool wait_for(
93  std::unique_lock<Mutex>& lock,
94  const std::chrono::nanoseconds& max_blocking_time,
95  std::function<bool()> predicate)
96  {
97  bool ret_value = true;
98  auto nsecs = max_blocking_time;
99  struct timespec max_wait = {
100  0, 0
101  };
102  clock_gettime(CLOCK_REALTIME, &max_wait);
103  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
104  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
105  nsecs -= secs;
106  max_wait.tv_sec += secs.count();
107  max_wait.tv_nsec = (long)nsecs.count();
108  while (ret_value && false == (ret_value = predicate()))
109  {
110  ret_value = (0 == CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(), &max_wait));
111  }
112 
113  return ret_value;
114  }
115 
116  template<typename Mutex>
117  bool wait_until(
118  std::unique_lock<Mutex>& lock,
119  const std::chrono::steady_clock::time_point& max_blocking_time,
120  std::function<bool()> predicate)
121  {
122  auto secs = std::chrono::time_point_cast<std::chrono::seconds>(max_blocking_time);
123  auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(max_blocking_time) -
124  std::chrono::time_point_cast<std::chrono::nanoseconds>(secs);
125  struct timespec max_wait = {
126  secs.time_since_epoch().count(), ns.count()
127  };
128  bool ret_value = true;
129  while (ret_value && false == (ret_value = predicate()))
130  {
131  ret_value = (CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(), &max_wait) == 0);
132  }
133 
134  return ret_value;
135  }
136 
137  template<typename Mutex>
138  bool wait_until(
139  std::unique_lock<Mutex>& lock,
140  const std::chrono::steady_clock::time_point& max_blocking_time)
141  {
142  auto secs = std::chrono::time_point_cast<std::chrono::seconds>(max_blocking_time);
143  auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(max_blocking_time) -
144  std::chrono::time_point_cast<std::chrono::nanoseconds>(secs);
145  struct timespec max_wait = {
146  secs.time_since_epoch().count(), ns.count()
147  };
148  return (CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(), &max_wait) == 0);
149  }
150 
151  void notify_one()
152  {
153  CV_SIGNAL_(cv_);
154  }
155 
156  void notify_all()
157  {
158  CV_BROADCAST_(cv_);
159  }
160 
161 private:
162 
163  CV_T_ cv_;
164 };
165 #else
166 using TimedConditionVariable = std::condition_variable_any;
167 #endif // HAVE_STRICT_REALTIME && (/*defined(_WIN32)*/ || defined(__unix__))
168 
169 } // namespace fastrtps
170 } // namespace eprosima
171 
172 #endif // _UTILS_TIMEDCONDITIONVARIABLE_HPP_
std::condition_variable_any TimedConditionVariable
Definition: TimedConditionVariable.hpp:166
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23