196 std::vector<std::function<void(ResultType)>> conts;
198 std::lock_guard<std::mutex> lock(mutex_);
199 if (value_.has_value())
return;
200 value_.emplace(
Unit{});
201 conts = std::move(continuations_);
204 for (
auto& cont : conts) {
213 std::vector<std::function<void(ResultType)>> conts;
215 std::lock_guard<std::mutex> lock(mutex_);
216 if (value_.has_value())
return;
218 conts = std::move(continuations_);
221 for (
auto& cont : conts) {
229 void cancel(std::string reason = {}) {
230 std::vector<std::function<void(ResultType)>> conts;
232 std::lock_guard<std::mutex> lock(mutex_);
233 if (value_.has_value())
return;
236 reason.empty() ?
"cancelled" : std::move(reason),
239 conts = std::move(continuations_);
242 for (
auto& cont : conts) {
250 ResultType
wait()
const {
251 std::unique_lock<std::mutex> lock(mutex_);
252 cv_.wait(lock, [
this]() {
return value_.has_value(); });
256 ResultType
wait_for(std::chrono::milliseconds timeout)
const {
257 std::unique_lock<std::mutex> lock(mutex_);
258 if (!cv_.wait_for(lock, timeout,
259 [
this]() { return value_.has_value(); })) {
260 return unexpected(
Error{1,
"AsyncResult wait timed out", {},
"timeout"});
265 ResultType
wait_until(std::chrono::steady_clock::time_point deadline)
const {
266 std::unique_lock<std::mutex> lock(mutex_);
267 if (!cv_.wait_until(lock, deadline,
268 [
this]() { return value_.has_value(); })) {
269 return unexpected(
Error{1,
"AsyncResult wait timed out", {},
"timeout"});
275 std::lock_guard<std::mutex> lock(mutex_);
276 return value_.has_value();
280 auto then(F&& callback)
281 -> std::shared_ptr<AsyncResult<std::invoke_result_t<F, ResultType>>> {
282 using R = std::invoke_result_t<F, ResultType>;
283 auto next = std::make_shared<AsyncResult<R>>();
284 std::optional<ResultType> ready_value;
286 std::lock_guard<std::mutex> lock(mutex_);
287 if (value_.has_value()) {
288 ready_value = *value_;
290 continuations_.emplace_back(
291 [next, cb = std::forward<F>(callback)](ResultType result)
mutable {
293 next->set_value(cb(std::move(result)));
295 next->set_exception(std::current_exception());
300 if (ready_value.has_value()) {
302 next->set_value(callback(std::move(*ready_value)));
304 next->set_exception(std::current_exception());
311 mutable std::mutex mutex_;
312 mutable std::condition_variable cv_;
313 std::optional<ResultType> value_;
314 std::vector<std::function<void(ResultType)>> continuations_;
ResultType wait_until(std::chrono::steady_clock::time_point deadline) const
Block until the result is available or the deadline is reached.
Definition async_result.hpp:111
ResultType wait_for(std::chrono::milliseconds timeout) const
Block until the result is available or the timeout expires.
Definition async_result.hpp:101
auto then(F &&callback) -> std::shared_ptr< AsyncResult< std::invoke_result_t< F, ResultType > > >
Chain a continuation that fires when the result is set.
Definition async_result.hpp:135