| Fast DDS Version 3.3.0 Fast DDS

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