Commit ff18deaf authored by Lee Howes's avatar Lee Howes Committed by Facebook Github Bot

Make consistent set of get and getTry methods on SemiFuture.

Summary: Complete set of get and getVia methods including addition of a result operation on FutureBase that provides functionality of the old getTry on Future by returning a Try by reference.

Reviewed By: yfeldblum

Differential Revision: D6640056

fbshipit-source-id: 3ac01f7bc4b128e641f08d9a99280a18ffce82f9
parent 661c75b6
/* /*
* Copyright 2017 Facebook, Inc. * Copyright 2017-present Facebook, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <algorithm> #include <algorithm>
...@@ -174,30 +173,50 @@ FutureBase<T>::~FutureBase() { ...@@ -174,30 +173,50 @@ FutureBase<T>::~FutureBase() {
template <class T> template <class T>
T& FutureBase<T>::value() & { T& FutureBase<T>::value() & {
return result().value();
}
template <class T>
T const& FutureBase<T>::value() const& {
return result().value();
}
template <class T>
T&& FutureBase<T>::value() && {
return std::move(result().value());
}
template <class T>
T const&& FutureBase<T>::value() const&& {
return std::move(result().value());
}
template <class T>
Try<T>& FutureBase<T>::result() & {
throwIfInvalid(); throwIfInvalid();
return core_->getTry().value(); return core_->getTry();
} }
template <class T> template <class T>
T const& FutureBase<T>::value() const& { Try<T> const& FutureBase<T>::result() const& {
throwIfInvalid(); throwIfInvalid();
return core_->getTry().value(); return core_->getTry();
} }
template <class T> template <class T>
T&& FutureBase<T>::value() && { Try<T>&& FutureBase<T>::result() && {
throwIfInvalid(); throwIfInvalid();
return std::move(core_->getTry().value()); return std::move(core_->getTry());
} }
template <class T> template <class T>
T const&& FutureBase<T>::value() const&& { Try<T> const&& FutureBase<T>::result() const&& {
throwIfInvalid(); throwIfInvalid();
return std::move(core_->getTry().value()); return std::move(core_->getTry());
} }
template <class T> template <class T>
...@@ -1443,7 +1462,7 @@ SemiFuture<T>&& SemiFuture<T>::waitVia(DrivableExecutor* e) && { ...@@ -1443,7 +1462,7 @@ SemiFuture<T>&& SemiFuture<T>::waitVia(DrivableExecutor* e) && {
template <class T> template <class T>
T SemiFuture<T>::get() && { T SemiFuture<T>::get() && {
return std::move(wait().value()); return std::move(wait()).value();
} }
template <class T> template <class T>
...@@ -1458,19 +1477,27 @@ T SemiFuture<T>::get(Duration dur) && { ...@@ -1458,19 +1477,27 @@ T SemiFuture<T>::get(Duration dur) && {
template <class T> template <class T>
Try<T> SemiFuture<T>::getTry() && { Try<T> SemiFuture<T>::getTry() && {
wait(); return std::move(wait()).result();
return std::move(this->core_->getTry()); }
template <class T>
Try<T> SemiFuture<T>::getTry(Duration dur) && {
wait(dur);
if (this->isReady()) {
return std::move(this->result());
} else {
throwTimedOut();
}
} }
template <class T> template <class T>
T SemiFuture<T>::getVia(DrivableExecutor* e) && { T SemiFuture<T>::getVia(DrivableExecutor* e) && {
return std::move(waitVia(e).value()); return std::move(waitVia(e)).value();
} }
template <class T> template <class T>
Try<T> SemiFuture<T>::getTryVia(DrivableExecutor* e) && { Try<T> SemiFuture<T>::getTryVia(DrivableExecutor* e) && {
waitVia(e); return std::move(waitVia(e)).result();
return std::move(this->core_->getTry());
} }
template <class T> template <class T>
...@@ -1526,9 +1553,7 @@ T Future<T>::get(Duration dur) { ...@@ -1526,9 +1553,7 @@ T Future<T>::get(Duration dur) {
template <class T> template <class T>
Try<T>& Future<T>::getTry() { Try<T>& Future<T>::getTry() {
throwIfInvalid(); return result();
return this->core_->getTry();
} }
template <class T> template <class T>
......
/* /*
* Copyright 2017 Facebook, Inc. * Copyright 2017-present Facebook, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <algorithm> #include <algorithm>
...@@ -97,6 +96,13 @@ class FutureBase { ...@@ -97,6 +96,13 @@ class FutureBase {
T&& value() &&; T&& value() &&;
T const&& value() const&&; T const&& value() const&&;
/// Returns a reference to the try of the result. Throws as for value if
/// future is not valid.
Try<T>& result() &;
Try<T> const& result() const&;
Try<T>&& result() &&;
Try<T> const&& result() const&&;
/** True when the result (or exception) is ready. */ /** True when the result (or exception) is ready. */
bool isReady() const; bool isReady() const;
...@@ -238,6 +244,7 @@ class SemiFuture : private futures::detail::FutureBase<T> { ...@@ -238,6 +244,7 @@ class SemiFuture : private futures::detail::FutureBase<T> {
using Base::raise; using Base::raise;
using Base::setCallback_; using Base::setCallback_;
using Base::value; using Base::value;
using Base::result;
SemiFuture& operator=(SemiFuture const&) = delete; SemiFuture& operator=(SemiFuture const&) = delete;
SemiFuture& operator=(SemiFuture&&) noexcept; SemiFuture& operator=(SemiFuture&&) noexcept;
...@@ -256,6 +263,10 @@ class SemiFuture : private futures::detail::FutureBase<T> { ...@@ -256,6 +263,10 @@ class SemiFuture : private futures::detail::FutureBase<T> {
/// Try of the value (moved out). /// Try of the value (moved out).
Try<T> getTry() &&; Try<T> getTry() &&;
/// Block until the future is fulfilled, or until timed out. Returns the
/// Try of the value (moved out) or may throw a TimedOut exception.
Try<T> getTry(Duration dur) &&;
/// Call e->drive() repeatedly until the future is fulfilled. Examples /// Call e->drive() repeatedly until the future is fulfilled. Examples
/// of DrivableExecutor include EventBase and ManualExecutor. Returns the /// of DrivableExecutor include EventBase and ManualExecutor. Returns the
/// value (moved out), or throws the exception. /// value (moved out), or throws the exception.
...@@ -419,6 +430,7 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -419,6 +430,7 @@ class Future : private futures::detail::FutureBase<T> {
using Base::raise; using Base::raise;
using Base::setCallback_; using Base::setCallback_;
using Base::value; using Base::value;
using Base::result;
static Future<T> makeEmpty(); // equivalent to moved-from static Future<T> makeEmpty(); // equivalent to moved-from
......
/* /*
* Copyright 2017 Facebook, Inc. * Copyright 2017-present Facebook, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <folly/Executor.h> #include <folly/Executor.h>
#include <folly/Memory.h> #include <folly/Memory.h>
#include <folly/Unit.h> #include <folly/Unit.h>
...@@ -264,6 +263,70 @@ TEST(SemiFuture, MakeFutureFromSemiFutureLValue) { ...@@ -264,6 +263,70 @@ TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
ASSERT_EQ(result, 42); ASSERT_EQ(result, 42);
} }
TEST(SemiFuture, SimpleGet) {
EventBase e2;
Promise<int> p;
auto sf = p.getSemiFuture();
p.setValue(3);
auto v = std::move(sf).get();
ASSERT_EQ(v, 3);
}
TEST(SemiFuture, SimpleGetTry) {
EventBase e2;
Promise<int> p;
auto sf = p.getSemiFuture();
p.setValue(3);
auto v = std::move(sf).getTry();
ASSERT_EQ(v.value(), 3);
}
TEST(SemiFuture, SimpleTimedGet) {
EventBase e2;
Promise<folly::Unit> p;
auto sf = p.getSemiFuture();
EXPECT_THROW(std::move(sf).get(std::chrono::seconds(1)), TimedOut);
}
TEST(SemiFuture, SimpleTimedGetTry) {
EventBase e2;
Promise<folly::Unit> p;
auto sf = p.getSemiFuture();
EXPECT_THROW(std::move(sf).getTry(std::chrono::seconds(1)), TimedOut);
}
TEST(SemiFuture, SimpleValue) {
EventBase e2;
Promise<int> p;
auto sf = p.getSemiFuture();
p.setValue(3);
auto v = std::move(sf).value();
ASSERT_EQ(v, 3);
}
TEST(SemiFuture, SimpleValueThrow) {
EventBase e2;
Promise<folly::Unit> p;
auto sf = p.getSemiFuture();
EXPECT_THROW(std::move(sf).value(), FutureNotReady);
}
TEST(SemiFuture, SimpleResult) {
EventBase e2;
Promise<int> p;
auto sf = p.getSemiFuture();
p.setValue(3);
auto v = std::move(sf).result();
ASSERT_EQ(v.value(), 3);
}
TEST(SemiFuture, SimpleResultThrow) {
EventBase e2;
Promise<folly::Unit> p;
auto sf = p.getSemiFuture();
EXPECT_THROW(std::move(sf).result(), FutureNotReady);
}
TEST(SemiFuture, SimpleDefer) { TEST(SemiFuture, SimpleDefer) {
std::atomic<int> innerResult{0}; std::atomic<int> innerResult{0};
Promise<folly::Unit> p; Promise<folly::Unit> p;
......
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