Fast RTPS  Version 2.14.5
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_condattr_init(&cv_attr_); \
46  pthread_condattr_setclock(&cv_attr_, CLOCK_MONOTONIC); \
47  pthread_cond_init(x, &cv_attr_);
48 #define CV_WAIT_(cv, x) pthread_cond_wait(&cv, x)
49 #define CV_TIMEDWAIT_(cv, x, y) pthread_cond_timedwait(&cv, x, y)
50 #define CV_SIGNAL_(cv) pthread_cond_signal(&cv)
51 #define CV_BROADCAST_(cv) pthread_cond_broadcast(&cv)
52 #define CV_T_ pthread_condattr_t cv_attr_; pthread_cond_t
53 #else
54 #include <condition_variable>
55 #endif // if HAVE_STRICT_REALTIME && defined(__unix__)
56 
57 #include <mutex>
58 #include <condition_variable>
59 #include <chrono>
60 #include <functional>
61 
62 namespace eprosima {
63 namespace fastrtps {
64 
65 #if HAVE_STRICT_REALTIME && (/*defined(_WIN32) ||*/ defined(__unix__))
66 
68 {
69 public:
70 
72  {
73  CV_INIT_(&cv_);
74  }
75 
76  template<typename Mutex>
77  void wait(
78  std::unique_lock<Mutex>& lock,
79  std::function<bool()> predicate)
80  {
81  while (!predicate())
82  {
83  CV_WAIT_(cv_, lock.mutex()->native_handle());
84  }
85  }
86 
87  template<typename Mutex>
88  void wait(
89  std::unique_lock<Mutex>& lock)
90  {
91  CV_WAIT_(cv_, lock.mutex()->native_handle());
92  }
93 
94  template<typename Mutex>
95  bool wait_for(
96  std::unique_lock<Mutex>& lock,
97  const std::chrono::nanoseconds& max_blocking_time,
98  std::function<bool()> predicate)
99  {
100  bool ret_value = true;
101  auto nsecs = max_blocking_time;
102  struct timespec max_wait = {
103  0, 0
104  };
105  clock_gettime(CLOCK_MONOTONIC, &max_wait);
106  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
107  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
108  nsecs -= secs;
109  max_wait.tv_sec += secs.count();
110  max_wait.tv_nsec = (long)nsecs.count();
111  while (ret_value && false == (ret_value = predicate()))
112  {
113  ret_value = (0 == CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(), &max_wait));
114  }
115 
116  return ret_value;
117  }
118 
119  template<typename Mutex>
120  std::cv_status wait_for(
121  std::unique_lock<Mutex>& lock,
122  const std::chrono::nanoseconds& max_blocking_time)
123  {
124  auto nsecs = max_blocking_time;
125  struct timespec max_wait = {
126  0, 0
127  };
128  clock_gettime(CLOCK_MONOTONIC, &max_wait);
129  nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
130  auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
131  nsecs -= secs;
132  max_wait.tv_sec += secs.count();
133  max_wait.tv_nsec = (long)nsecs.count();
134  return (CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(),
135  &max_wait) == 0) ? std::cv_status::no_timeout : std::cv_status::timeout;
136  }
137 
138  template<typename Mutex>
139  bool wait_until(
140  std::unique_lock<Mutex>& lock,
141  const std::chrono::steady_clock::time_point& max_blocking_time,
142  std::function<bool()> predicate)
143  {
144  auto secs = std::chrono::time_point_cast<std::chrono::seconds>(max_blocking_time);
145  auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(max_blocking_time) -
146  std::chrono::time_point_cast<std::chrono::nanoseconds>(secs);
147  struct timespec max_wait = {
148  secs.time_since_epoch().count(), ns.count()
149  };
150  bool ret_value = true;
151  while (ret_value && false == (ret_value = predicate()))
152  {
153  ret_value = (CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(), &max_wait) == 0);
154  }
155 
156  return ret_value;
157  }
158 
159  template<typename Mutex>
160  std::cv_status wait_until(
161  std::unique_lock<Mutex>& lock,
162  const std::chrono::steady_clock::time_point& max_blocking_time)
163  {
164  auto secs = std::chrono::time_point_cast<std::chrono::seconds>(max_blocking_time);
165  auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(max_blocking_time) -
166  std::chrono::time_point_cast<std::chrono::nanoseconds>(secs);
167  struct timespec max_wait = {
168  secs.time_since_epoch().count(), ns.count()
169  };
170  return (CV_TIMEDWAIT_(cv_, lock.mutex()->native_handle(),
171  &max_wait) == 0) ? std::cv_status::no_timeout : std::cv_status::timeout;
172  }
173 
174  void notify_one()
175  {
176  CV_SIGNAL_(cv_);
177  }
178 
179  void notify_all()
180  {
181  CV_BROADCAST_(cv_);
182  }
183 
184 private:
185 
186  CV_T_ cv_;
187 };
188 #else
189 using TimedConditionVariable = std::condition_variable_any;
190 #endif // HAVE_STRICT_REALTIME && (/*defined(_WIN32)*/ || defined(__unix__))
191 
192 } // namespace fastrtps
193 } // namespace eprosima
194 
195 #endif // _UTILS_TIMEDCONDITIONVARIABLE_HPP_
std::condition_variable_any TimedConditionVariable
Definition: TimedConditionVariable.hpp:189
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23