26#include <seastar/core/future.hh>
27#include <seastar/core/abortable_fifo.hh>
28#include <seastar/core/abort_on_expiry.hh>
29#include <seastar/core/timed_out_error.hh>
30#include <seastar/util/modules.hh>
41template<
typename Clock>
46template <
typename... T>
47struct future_option_traits;
49template <
typename Clock,
typename T>
50struct future_option_traits<
with_clock<Clock>, T> {
51 using clock_type = Clock;
57template <
typename Clock>
58struct future_option_traits<with_clock<Clock>> {
59 using clock_type = Clock;
61 using future_type = future<>;
66struct future_option_traits<T> :
public future_option_traits<with_clock<lowres_clock>, T> {
70struct future_option_traits<> : future_option_traits<void> {
107template<
typename... T>
110 using options = future_option_traits<T...>;
112 using clock =
typename options::clock_type;
113 using time_point =
typename clock::time_point;
114 using future_type =
typename future_option_traits<T...>::future_type;
115 using promise_type =
typename future_option_traits<T...>::promise_type;
116 using value_tuple_type =
typename future_type::tuple_type;
120 future_type _original_future;
125 std::optional<abort_on_expiry<clock>>
timer;
128 struct entry_expiry {
129 void operator()(entry& e)
noexcept {
138 internal::abortable_fifo<entry, entry_expiry> _peers;
145 if (_original_future.failed()) {
146 _original_future.ignore_ready_future();
149 explicit shared_state(future_type f) noexcept
150 :
task(default_scheduling_group())
151 , _original_future(std::move(f)) {
153 void run_and_dispose()
noexcept override {
154 auto& state = _original_future._state;
155 if (_original_future.failed()) {
157 _peers.front().pr.set_exception(state.get_exception());
162 auto& p = _peers.front().pr;
164 p.set_value(state.get_value());
166 p.set_exception(std::current_exception());
174 _keepaliver.release();
177 task* waiting_task()
noexcept override {
181 future_type
get_future(time_point timeout = time_point::max())
noexcept {
189 if (!_original_future.available()) {
190 entry& e = _peers.emplace_back();
192 auto f = e.pr.get_future();
193 if (timeout != time_point::max()) {
194 e.timer.emplace(timeout);
196 _peers.make_back_abortable(as);
200 _original_future.set_task(*
this);
201 _keepaliver = this->shared_from_this();
204 }
else if (_original_future.failed()) {
219 if (!_original_future.available()) {
220 entry& e = _peers.emplace_back();
222 auto f = e.pr.get_future();
223 _peers.make_back_abortable(as);
226 _original_future.set_task(*
this);
227 _keepaliver = this->shared_from_this();
230 }
else if (_original_future.failed()) {
238 return _original_future.available();
241 bool failed()
const noexcept {
242 return _original_future.failed();
246 bool has_scheduled_task()
const noexcept {
247 return _keepaliver !=
nullptr;
255 : _state(make_lw_shared<shared_state>(
std::move(f))) { }
269 future_type
get_future(time_point timeout = time_point::max()) const noexcept {
270 return _state->get_future(timeout);
280 return _state->get_future(as);
287 return _state->available();
294 return _state->failed();
298 operator future_type() const noexcept {
308 friend class shared_future_tester;
318template <
typename... T>
322 using future_type =
typename shared_future_type::future_type;
323 using promise_type =
typename shared_future_type::promise_type;
324 using clock =
typename shared_future_type::clock;
325 using time_point =
typename shared_future_type::time_point;
326 using value_tuple_type =
typename shared_future_type::value_tuple_type;
328 promise_type _promise;
330 static constexpr bool copy_noexcept = future_type::copy_noexcept;
335 shared_promise() : _promise(), _shared_future(_promise.get_future()) {
354 void set_value(
const value_tuple_type& result)
noexcept(copy_noexcept) {
355 _promise.set_value(result);
360 _promise.set_value(std::move(result));
364 template <
typename... A>
366 _promise.set_value(std::forward<A>(a)...);
371 _promise.set_exception(std::move(ex));
375 template<
typename Exception>
377 set_exception(make_exception_ptr(std::forward<Exception>(e)));
387 return _shared_future.
failed();
Definition: abort_source.hh:48
Definition: abort_source.hh:58
Definition: shared_ptr.hh:148
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
promise - allows a future value to be made available at a later time.
Definition: future.hh:934
Like future except the result can be waited for by many fibers.
Definition: shared_future.hh:108
bool available() const noexcept
Returns true if the future is available (ready or failed)
Definition: shared_future.hh:286
shared_future(future_type f)
Forwards the result of future f into this shared_future.
Definition: shared_future.hh:254
future_type get_future(abort_source &as) const noexcept
Creates a new future which will resolve with the result of this shared_future.
Definition: shared_future.hh:279
bool failed() const noexcept
Returns true if the future is failed.
Definition: shared_future.hh:293
bool valid() const noexcept
Returns true if the instance is in valid state.
Definition: shared_future.hh:303
future_type get_future(time_point timeout=time_point::max()) const noexcept
Creates a new future which will resolve with the result of this shared_future.
Definition: shared_future.hh:269
Like promise except that its counterpart is shared_future instead of future.
Definition: shared_future.hh:319
void set_exception(Exception &&e) noexcept
Marks the shared_promise as failed, same as normal promise.
Definition: shared_future.hh:376
void set_value(value_tuple_type &&result) noexcept
Sets the shared_promise's value (as tuple; by moving), same as normal promise.
Definition: shared_future.hh:359
bool failed() const noexcept
Returns true if the underlying future is failed.
Definition: shared_future.hh:386
void set_exception(std::exception_ptr ex) noexcept
Marks the shared_promise as failed, same as normal promise.
Definition: shared_future.hh:370
void set_value(const value_tuple_type &result) noexcept(copy_noexcept)
Sets the shared_promise's value (as tuple; by copying), same as normal promise.
Definition: shared_future.hh:354
future_type get_shared_future(time_point timeout=time_point::max()) const noexcept
Gets new future associated with this promise. If the promise is not resolved before timeout the retur...
Definition: shared_future.hh:341
future_type get_shared_future(abort_source &as) const noexcept
Gets new future associated with this promise. If the promise is not resolved before abort source is t...
Definition: shared_future.hh:349
void set_value(A &&... a) noexcept
Sets the shared_promise's value (variadic), same as normal promise.
Definition: shared_future.hh:365
bool available() const noexcept
Returns true if the underlying future is available (ready or failed)
Definition: shared_future.hh:381
Definition: timed_out_error.hh:34
Definition: future.hh:566
Definition: future.hh:565
Changes the clock used by shared_future<> and shared_promise<> when passed as the first template para...
Definition: shared_future.hh:42
Definition: critical_alloc_section.hh:80
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
scheduling_group current_scheduling_group() noexcept
Returns the current scheduling group.
Definition: scheduling.hh:397