Commit ffcba177 authored by Marshall Cline's avatar Marshall Cline Committed by Facebook Github Bot

modernize Future::get(): 1/n = add rval-qual overload invalidates *this

Summary: Add rvalue-qualified overloads of Future::get() and get(dur) which invalidate their this-object.

Reviewed By: yfeldblum

Differential Revision: D8242442

fbshipit-source-id: 4dea8a41878d59f6088504df2b8b3e686d581c89
parent edd050b1
...@@ -2025,12 +2025,28 @@ Future<T>&& Future<T>::waitVia(TimedDrivableExecutor* e, Duration dur) && { ...@@ -2025,12 +2025,28 @@ Future<T>&& Future<T>::waitVia(TimedDrivableExecutor* e, Duration dur) && {
} }
template <class T> template <class T>
T Future<T>::get() { T Future<T>::get() && {
wait();
return copy(std::move(*this)).value();
}
template <class T>
T Future<T>::get() & {
return std::move(wait().value()); return std::move(wait().value());
} }
template <class T> template <class T>
T Future<T>::get(Duration dur) { T Future<T>::get(Duration dur) && {
wait(dur);
auto future = copy(std::move(*this));
if (!future.isReady()) {
throw_exception<FutureTimeout>();
}
return std::move(future).value();
}
template <class T>
T Future<T>::get(Duration dur) & {
wait(dur); wait(dur);
if (!this->isReady()) { if (!this->isReady()) {
throw_exception<FutureTimeout>(); throw_exception<FutureTimeout>();
......
...@@ -1519,7 +1519,13 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1519,7 +1519,13 @@ class Future : private futures::detail::FutureBase<T> {
/// Postconditions: /// Postconditions:
/// ///
/// - `valid() == false` /// - `valid() == false`
T get(); T get() &&;
/// Blocks until the future is fulfilled. Returns the value (moved out), or
/// throws the exception. The future must not already have a callback.
///
/// Deprecated in favor of `get() &&`.
T get() &;
/// Blocks until the future is fulfilled, or until `dur` elapses. Returns the /// Blocks until the future is fulfilled, or until `dur` elapses. Returns the
/// value (moved-out), or throws the exception (which might be a FutureTimeout /// value (moved-out), or throws the exception (which might be a FutureTimeout
...@@ -1532,7 +1538,14 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1532,7 +1538,14 @@ class Future : private futures::detail::FutureBase<T> {
/// Postconditions: /// Postconditions:
/// ///
/// - `valid() == false` /// - `valid() == false`
T get(Duration dur); T get(Duration dur) &&;
/// Blocks until the future is fulfilled, or until `dur` elapses. Returns the
/// value (moved out), or throws the exception (which might be a FutureTimeout
/// exception).
///
/// Deprecated in favor of `get(Duration) &&`.
T get(Duration dur) &;
/// A reference to the Try of the value /// A reference to the Try of the value
/// ///
......
...@@ -82,6 +82,45 @@ TEST(Future, makeFutureWithUnit) { ...@@ -82,6 +82,45 @@ TEST(Future, makeFutureWithUnit) {
EXPECT_EQ(1, count); EXPECT_EQ(1, count);
} }
TEST(Future, getRequiresOnlyMoveCtor) {
struct MoveCtorOnly {
MoveCtorOnly(const MoveCtorOnly&) = delete;
MoveCtorOnly(MoveCtorOnly&&) = default;
MoveCtorOnly(int id) : id_(id) {}
void operator=(MoveCtorOnly const&) = delete;
void operator=(MoveCtorOnly&&) = delete;
int id_;
};
{
auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
EXPECT_TRUE(f.valid());
EXPECT_TRUE(f.isReady());
auto v = f.get();
EXPECT_EQ(v.id_, 42);
}
{
auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
EXPECT_TRUE(f.valid());
EXPECT_TRUE(f.isReady());
auto v = std::move(f).get();
EXPECT_EQ(v.id_, 42);
}
{
auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
EXPECT_TRUE(f.valid());
EXPECT_TRUE(f.isReady());
auto v = f.get(std::chrono::milliseconds(10));
EXPECT_EQ(v.id_, 42);
}
{
auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
EXPECT_TRUE(f.valid());
EXPECT_TRUE(f.isReady());
auto v = std::move(f).get(std::chrono::milliseconds(10));
EXPECT_EQ(v.id_, 42);
}
}
namespace { namespace {
auto makeValid() { auto makeValid() {
auto valid = makeFuture<int>(42); auto valid = makeFuture<int>(42);
...@@ -194,6 +233,10 @@ TEST(Future, hasPreconditionValid) { ...@@ -194,6 +233,10 @@ TEST(Future, hasPreconditionValid) {
DOIT(f.isReady()); DOIT(f.isReady());
DOIT(f.result()); DOIT(f.result());
DOIT(f.get());
DOIT(f.get(std::chrono::milliseconds(10)));
DOIT(std::move(f).get());
DOIT(std::move(f).get(std::chrono::milliseconds(10)));
DOIT(f.getTry()); DOIT(f.getTry());
DOIT(f.hasValue()); DOIT(f.hasValue());
DOIT(f.hasException()); DOIT(f.hasException());
...@@ -227,6 +270,7 @@ TEST(Future, hasPostconditionValid) { ...@@ -227,6 +270,7 @@ TEST(Future, hasPostconditionValid) {
DOIT(f.raise(std::logic_error("foo"))); DOIT(f.raise(std::logic_error("foo")));
DOIT(f.cancel()); DOIT(f.cancel());
DOIT(swallow(f.get())); DOIT(swallow(f.get()));
DOIT(swallow(f.get(std::chrono::milliseconds(10))));
DOIT(swallow(f.getTry())); DOIT(swallow(f.getTry()));
DOIT(f.wait()); DOIT(f.wait());
DOIT(std::move(f.wait())); DOIT(std::move(f.wait()));
...@@ -280,6 +324,8 @@ TEST(Future, hasPostconditionInvalid) { ...@@ -280,6 +324,8 @@ TEST(Future, hasPostconditionInvalid) {
auto const swallow = [](auto) {}; auto const swallow = [](auto) {};
DOIT(makeValid(), swallow(std::move(f).wait())); DOIT(makeValid(), swallow(std::move(f).wait()));
DOIT(makeValid(), swallow(std::move(f.wait()))); DOIT(makeValid(), swallow(std::move(f.wait())));
DOIT(makeValid(), swallow(std::move(f).get()));
DOIT(makeValid(), swallow(std::move(f).get(std::chrono::milliseconds(10))));
DOIT(makeValid(), swallow(f.semi())); DOIT(makeValid(), swallow(f.semi()));
#undef DOIT #undef DOIT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment