utils: add a timeout to ImmediateFuture::{get,getTry}

Summary:
This is to mimic the folly::Future API which allows the `get` and `getTry` to
throw if the Future isn't ready. One difference is that the ImmediateFuture API
has a default argument of a max duration instead of having a separate method.
Since chrono durations are expressed as intmax_t (64-bits on systems supported
by EdenFS) a max duration is virtually infinite.

Reviewed By: chadaustin

Differential Revision: D28424053

fbshipit-source-id: 319493174f31367184dbe0aa811a97145b0310cf
This commit is contained in:
Xavier Deguillard 2021-05-17 14:05:54 -07:00 committed by Facebook GitHub Bot
parent d0327a20ce
commit 3863a8972a
3 changed files with 20 additions and 8 deletions

View File

@ -59,28 +59,28 @@ ImmediateFuture<T>::thenTry(Func&& func) && {
}
template <typename T>
T ImmediateFuture<T>::get() && {
T ImmediateFuture<T>::get(folly::HighResDuration timeout) && {
return std::visit(
[](auto&& inner) -> T {
[timeout](auto&& inner) -> T {
using Type = std::decay_t<decltype(inner)>;
if constexpr (std::is_same_v<Type, folly::Try<T>>) {
return std::move(inner).value();
} else {
return std::move(inner).get();
return std::move(inner).get(timeout);
}
},
std::move(inner_));
}
template <typename T>
folly::Try<T> ImmediateFuture<T>::getTry() && {
folly::Try<T> ImmediateFuture<T>::getTry(folly::HighResDuration timeout) && {
return std::visit(
[](auto&& inner) -> folly::Try<T> {
[timeout](auto&& inner) -> folly::Try<T> {
using Type = std::decay_t<decltype(inner)>;
if constexpr (std::is_same_v<Type, folly::Try<T>>) {
return std::move(inner);
} else {
return std::move(inner).getTry();
return std::move(inner).getTry(timeout);
}
},
std::move(inner_));

View File

@ -126,15 +126,20 @@ class ImmediateFuture {
* exception.
*
* When the future is an immediate value, this returns without waiting.
*
* A folly::FutureTimeout will be thrown if the timeout is reached.
*/
T get() &&;
T get(folly::HighResDuration timeout = folly::HighResDuration::max()) &&;
/**
* Wait for the future to complete and return the Try value.
*
* When the future is an immediate value, this returns without waiting.
*
* A folly::FutureTimeout will be thrown if the timeout is reached.
*/
folly::Try<T> getTry() &&;
folly::Try<T> getTry(
folly::HighResDuration timeout = folly::HighResDuration::max()) &&;
bool hasImmediate() const {
return std::holds_alternative<folly::Try<T>>(inner_);

View File

@ -11,6 +11,7 @@
#include <gtest/gtest.h>
using namespace facebook::eden;
using namespace std::literals::chrono_literals;
TEST(ImmediateFuture, get) {
int value = 42;
@ -171,3 +172,9 @@ TEST(ImmediateFuture, mutableLambda) {
[foo](auto&& value) mutable { return value + foo.getNonConstVal(); });
EXPECT_EQ(std::move(setFooFut).get(), 43);
}
TEST(ImmediateFuture, getTimeout) {
auto [promise, semiFut] = folly::makePromiseContract<int>();
ImmediateFuture<int> fut{std::move(semiFut)};
EXPECT_THROW(std::move(fut).get(0ms), folly::FutureTimeout);
}