9#ifndef STLAB_CONCURRENCY_AWAIT_HPP
10#define STLAB_CONCURRENCY_AWAIT_HPP
24#include <stlab/config.hpp>
27#include <condition_variable>
33#include <stlab/concurrency/immediate_executor.hpp>
37#include <stlab/concurrency/default_executor.hpp>
42STLAB_VERSION_NAMESPACE_BEGIN()
57 if (!stlab_v2_default_executor_supports_blocking()) std::terminate();
58 stlab_v2_notify_default_executor_before_waiting();
60 return std::forward<F>(f)();
72 if (x.is_ready())
return std::move(x).get_ready();
73 if (!stlab_v2_default_executor_supports_blocking()) std::terminate();
76 std::condition_variable condition;
79 auto hold = std::move(x).recover(immediate_executor, [&](
future<T>&& r) {
81 std::unique_lock<std::mutex> lock{m};
82 result = std::move(r);
83 condition.notify_one();
86 std::unique_lock<std::mutex> lock{m};
87 invoke_waiting([&] { condition.wait(lock, [&] {
return result.is_ready(); }); });
88 return std::move(result).get_ready();
94[[deprecated(
"implicit copy deprecated, use `await(std::move(f))` or `await(stlab::copy(f))`"
103struct blocking_get_guarded {
104 bool _timed_out{
false};
106 std::condition_variable _condition;
110 auto set(F&& r) -> future<T> {
112 std::unique_lock<std::mutex> lock{_mutex};
113 if (_timed_out)
return std::forward<F>(r);
114 _result = std::forward<F>(r);
116 _condition.notify_one();
123 std::make_exception_ptr(std::runtime_error(
"not an error")), immediate_executor);
126 auto wait_for(
const std::chrono::nanoseconds& timeout) -> future<T> {
127 std::unique_lock<std::mutex> lock{_mutex};
129 [&] {
return _condition.wait_for(lock, timeout, [&] {
return _result.valid(); }); });
130 return _timed_out ? future<T>{} : std::move(_result);
141 if (x.is_ready() || !stlab_v2_default_executor_supports_blocking())
return std::move(x);
143 auto p = std::make_shared<detail::blocking_get_guarded<T>>();
146 if (
auto p = _p.lock())
return p->set(std::forward<
decltype(r)>(r));
147 return std::forward<decltype(r)>(r);
150 auto result = p->wait_for(timeout);
151 return result.valid() ? std::move(result) : std::move(hold);
157[[deprecated(
"implicit copy deprecated, use `await_for(std::move(f), t)` or"
158 " `await_for(stlab::copy(f), t)` instead.")]]
167STLAB_VERSION_NAMESPACE_END()
One-shot asynchronous result: holds a value or exception produced by a promise or packaged_task.
Definition future.hpp:306
Futures, packaged tasks, and coroutine integration.
auto await(future< T > &&x) -> T
Synchronously wait for the result x. If x resolves as an exception, the exception is rethrown....
Definition await.hpp:71
auto invoke_waiting(F &&f)
Assumes f will block waiting; on the portable task system, wakes the pool or adds a worker (up to the...
Definition await.hpp:56
auto await_for(future< T > &&x, const std::chrono::nanoseconds &timeout) -> future< T >
Waits at most timeout, returning a future that retains any pending result. In cooperative threadless ...
Definition await.hpp:140
auto make_exceptional_future(const std::exception_ptr &error, E executor) -> future< T >
Creates a future already failed with error (executor runs attached continuations).
Definition ready_future.hpp:86
auto make_weak_ptr(const std::shared_ptr< T > &x)
Returns a std::weak_ptr<T> sharing ownership with x.
Definition memory.hpp:35
Small memory-related utilities (make_weak_ptr).
Definition reverse.hpp:28
Factory functions for already-resolved futures.