blob: 6e03fed6e961ba7dc2676d0829adefde881bf63a [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_FORENSICS_UTILS_PROMISE_TIMEOUT_H_
#define SRC_DEVELOPER_FORENSICS_UTILS_PROMISE_TIMEOUT_H_
#include <lib/async/cpp/task.h>
#include <lib/async/dispatcher.h>
#include <lib/fpromise/bridge.h>
#include <lib/fpromise/promise.h>
#include <lib/zx/time.h>
#include "src/developer/forensics/utils/errors.h"
namespace forensics {
namespace internal {
template <typename Promise>
class timeout_continuation final {
public:
explicit timeout_continuation(Promise promise, Promise timeout_promise)
: promise_(std::move(promise)), timeout_promise_(std::move(timeout_promise)) {}
typename Promise::result_type operator()(fpromise::context& context) {
if (typename Promise::result_type result = promise_(context); !result.is_pending()) {
return std::move(result);
}
if (typename Promise::result_type result = timeout_promise_(context); !result.is_pending()) {
return std::move(result);
}
return fpromise::pending();
}
private:
Promise promise_;
Promise timeout_promise_;
};
template <typename Value>
fpromise::promise<Value, Error> make_timeout_promise(async_dispatcher_t* dispatcher,
zx::duration timeout) {
fpromise::bridge<Value, Error> bridge;
async::PostDelayedTask(
dispatcher,
[completer = std::move(bridge.completer)]() mutable {
completer.complete_error(Error::kTimeout);
},
timeout);
return bridge.consumer.promise();
}
} // namespace internal
// Returns Error::kTimeout if |promise| does not complete within |timeout|.
template <typename Value>
fpromise::promise<Value, Error> MakePromiseTimeout(fpromise::promise<Value, Error> promise,
async_dispatcher_t* dispatcher,
const zx::duration timeout) {
fpromise::promise<Value, Error> timeout_promise =
internal::make_timeout_promise<Value>(dispatcher, timeout);
return fpromise::make_promise_with_continuation(
internal::timeout_continuation<fpromise::promise<Value, Error>>(std::move(promise),
std::move(timeout_promise)));
}
} // namespace forensics
#endif // SRC_DEVELOPER_FORENSICS_UTILS_PROMISE_TIMEOUT_H_