9#ifndef STLAB_CONCURRENCY_AWAIT_HPP
10#define STLAB_CONCURRENCY_AWAIT_HPP
24#include <stlab/config.hpp>
27#include <condition_variable>
37#if STLAB_TASK_SYSTEM(PORTABLE)
44STLAB_VERSION_NAMESPACE_BEGIN()
58#if STLAB_TASK_SYSTEM(PORTABLE)
59 if (!detail::pts().wake()) detail::pts().add_thread();
62 return std::forward<F>(f)();
73 if (x.is_ready())
return std::move(x).get_ready();
76 std::condition_variable condition;
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();
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);
138 if (x.is_ready())
return std::move(x);
140 auto p = std::make_shared<detail::blocking_get_guarded<T>>();
143 if (
auto p = _p.lock())
return p->set(std::forward<
decltype(r)>(r));
144 return std::forward<decltype(r)>(r);
147 auto result = p->wait_for(timeout);
148 return result.valid() ? std::move(result) : std::
move(hold);
154[[deprecated(
"implicit copy deprecated, use `await_for(std::move(f), t)` or"
155 " `await_for(stlab::copy(f), t)` instead.")]]
169[[deprecated(
"Use await instead.")]]
171 return await(std::move(x));
176[[deprecated(
"Use await_for instead.")]]
178 return await_for(std::move(x), timeout);
183[[deprecated(
"Use await_for instead.")]]
192STLAB_VERSION_NAMESPACE_END()
One-shot asynchronous result: holds a value or exception produced by a promise or packaged_task.
Definition future.hpp:300
Thread-pool executors mapping to the OS scheduler (libdispatch, Windows pool, portable).
Futures, packaged tasks, channels, 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:72
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:57
auto blocking_get(future< T > x) -> T
Definition await.hpp:170
auto blocking_get_for(future< T > x, const std::chrono::nanoseconds &timeout) -> future< T >
Definition await.hpp:177
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
constexpr auto move(T &&t) noexcept -> std::remove_reference_t< T > &&
A standard move implementation but with a compile-time check for const types.
Definition utility.hpp:154
Small memory-related utilities (make_weak_ptr).
Definition reverse.hpp:28
Factory functions for already-resolved futures.