24 #ifndef SEASTAR_MODULE
25 #include <boost/intrusive/list.hpp>
32 #ifdef SEASTAR_COROUTINES_ENABLED
33 # include <seastar/core/coroutine.hh>
35 #include <seastar/core/loop.hh>
36 #include <seastar/util/modules.hh>
40 SEASTAR_MODULE_EXPORT_BEGIN
50 virtual const char*
what() const noexcept;
58 virtual const char*
what() const noexcept;
78 struct waiter :
public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
80 waiter(waiter&&) =
default;
81 waiter(
const waiter&) =
delete;
82 waiter& operator=(
const waiter&) =
delete;
83 virtual ~waiter() =
default;
84 void timeout() noexcept;
86 virtual void signal() noexcept = 0;
87 virtual void set_exception(std::exception_ptr) noexcept = 0;
90 struct promise_waiter :
public waiter,
public promise<> {
91 void signal() noexcept
override {
98 void set_exception(std::exception_ptr ep) noexcept
override {
105 #ifdef SEASTAR_COROUTINES_ENABLED
106 struct [[nodiscard("must co_await a when() call")]] awaiter :
public waiter {
114 void signal() noexcept
override {
117 void set_exception(std::exception_ptr ep) noexcept
override {
120 auto operator co_await() {
121 if (_cv->check_and_consume_signal()) {
122 return ::seastar::internal::awaiter<false, void>(make_ready_future<>());
124 _cv->add_waiter(*
this);
125 return ::seastar::internal::awaiter<false, void>(_p.
get_future());
129 template<
typename Clock,
typename Duration>
130 struct [[nodiscard("must co_await a when() call")]] timeout_awaiter :
public awaiter,
public timer<Clock> {
131 using my_type = timeout_awaiter<Clock, Duration>;
132 using time_point = std::chrono::time_point<Clock, Duration>;
140 void signal() noexcept
override {
144 void set_exception(std::exception_ptr ep) noexcept
override {
146 awaiter::set_exception(std::move(ep));
148 auto operator co_await() {
149 if (_cv->check_and_consume_signal()) {
150 return ::seastar::internal::awaiter<false, void>(make_ready_future<>());
152 this->set_callback(std::bind(&waiter::timeout,
this));
154 return awaiter::operator co_await();
158 template<
typename Func,
typename Base>
159 struct [[nodiscard("must co_await a when() call")]] predicate_awaiter :
public Base {
161 template<
typename... Args>
162 predicate_awaiter(Func func, Args&& ...args)
163 : Base(std::forward<Args>(args)...)
164 , _func(std::move(func))
166 void signal() noexcept
override {
174 Base::_cv->add_waiter(*
this);
177 auto operator co_await() {
179 return ::seastar::internal::awaiter<false, void>(make_ready_future<>());
181 Base::_cv->check_and_consume_signal();
182 return Base::operator co_await();
188 boost::intrusive::list<waiter, boost::intrusive::constant_time_size<false>> _waiters;
189 std::exception_ptr _ex;
190 bool _signalled =
false;
192 void add_waiter(waiter&) noexcept;
193 void timeout(waiter&) noexcept;
194 bool wakeup_first() noexcept;
195 bool check_and_consume_signal() noexcept;
210 if (check_and_consume_signal()) {
213 auto* w =
new promise_waiter;
214 auto f = w->get_future();
226 template<typename Clock = typename timer<>::clock,
typename Duration =
typename Clock::duration>
227 future<> wait(std::chrono::time_point<Clock, Duration> timeout) noexcept {
228 if (check_and_consume_signal()) {
231 struct timeout_waiter :
public promise_waiter,
public timer<Clock> {};
233 auto w = std::make_unique<timeout_waiter>();
234 auto f = w->get_future();
236 w->set_callback(std::bind(&waiter::timeout, w.get()));
238 add_waiter(*w.release());
249 template<
typename Rep,
typename Period>
261 template<
typename Pred>
262 SEASTAR_CONCEPT( requires std::is_invocable_r_v<bool, Pred> )
264 return do_until(std::forward<Pred>(pred), [
this] {
278 template<typename Clock = typename timer<>::clock,
typename Duration =
typename Clock::duration,
typename Pred>
279 SEASTAR_CONCEPT( requires std::is_invocable_r_v<bool, Pred> )
280 future<> wait(std::chrono::time_point<Clock, Duration> timeout, Pred&& pred) noexcept {
281 return do_until(std::forward<Pred>(pred), [
this, timeout] {
282 return wait(timeout);
295 template<
typename Rep,
typename Period,
typename Pred>
296 SEASTAR_CONCEPT( requires std::is_invocable_r_v<bool, Pred> )
297 future<> wait(std::chrono::duration<Rep, Period> timeout, Pred&& pred) noexcept {
301 #ifdef SEASTAR_COROUTINES_ENABLED
308 awaiter when() noexcept {
309 return awaiter{
this};
320 template<typename Clock = typename timer<>::clock,
typename Duration =
typename Clock::duration>
321 timeout_awaiter<Clock, Duration> when(std::chrono::time_point<Clock, Duration> timeout) noexcept {
322 return timeout_awaiter<Clock, Duration>{
this, timeout};
333 template<
typename Rep,
typename Period>
334 auto when(std::chrono::duration<Rep, Period> timeout) noexcept {
346 template<
typename Pred>
347 SEASTAR_CONCEPT( requires std::is_invocable_r_v<bool, Pred> )
348 auto when(Pred&& pred) noexcept {
349 return predicate_awaiter<Pred, awaiter>{std::forward<Pred>(pred), when()};
362 template<typename Clock = typename timer<>::clock,
typename Duration =
typename Clock::duration,
typename Pred>
363 SEASTAR_CONCEPT( requires std::is_invocable_r_v<bool, Pred> )
364 auto when(std::chrono::time_point<Clock, Duration> timeout, Pred&& pred) noexcept {
365 return predicate_awaiter<Pred, timeout_awaiter<Clock, Duration>>{std::forward<Pred>(pred), when(timeout)};
378 template<
typename Rep,
typename Period,
typename Pred>
379 SEASTAR_CONCEPT( requires std::is_invocable_r_v<bool, Pred> )
380 auto when(std::chrono::duration<Rep, Period> timeout, Pred&& pred) noexcept {
389 return !_waiters.empty();
396 void broadcast() noexcept;
401 void broken() noexcept;
403 void broken(std::exception_ptr) noexcept;
408 SEASTAR_MODULE_EXPORT_END
Definition: condition-variable.hh:47
virtual const char * what() const noexcept
Reports the exception reason.
Definition: condition-variable.hh:55
virtual const char * what() const noexcept
Reports the exception reason.
Conditional variable.
Definition: condition-variable.hh:74
bool has_waiters() const noexcept
Definition: condition-variable.hh:388
future wait(std::chrono::time_point< Clock, Duration > timeout) noexcept
Definition: condition-variable.hh:227
void signal() noexcept
Notify variable and wake up a waiter if there is one.
future wait(std::chrono::duration< Rep, Period > timeout) noexcept
Definition: condition-variable.hh:250
condition_variable() noexcept=default
A representation of a possibly not-yet-computed value.
Definition: future.hh:1238
promise - allows a future value to be made available at a later time.
Definition: future.hh:926
void set_value(A &&... a) noexcept
Sets the promises value.
Definition: future.hh:982
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:990
future< T > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:1934
future< T > get_future() noexcept
Gets the promise's associated future.
Definition: future.hh:1917
future do_until(StopCondition stop_cond, AsyncAction action) noexcept
Definition: loop.hh:339
future now()
Returns a ready future.
Definition: later.hh:35
Seastar API namespace.
Definition: abort_on_ebadf.hh:26