Commit cc7a5803 authored by Hans Fugal's avatar Hans Fugal Committed by Sara Golemon

Future::unit()

Summary: Discard a result but propagate an exception. cf https://www.facebook.com/groups/715931878455430/permalink/879624552086161/

Reviewed By: @​sammerat

Differential Revision: D2144567
parent 42111d87
......@@ -49,14 +49,10 @@ Future<T>::Future(T2&& val)
: core_(new detail::Core<T>(Try<T>(std::forward<T2>(val)))) {}
template <class T>
template <class T2,
typename std::enable_if<
folly::is_void_or_unit<T2>::value,
int>::type>
template <typename, typename>
Future<T>::Future()
: core_(new detail::Core<T>(Try<T>())) {}
template <class T>
Future<T>::~Future() {
detach();
......@@ -452,6 +448,16 @@ bool Future<T>::isReady() const {
return core_->ready();
}
template <class T>
bool Future<T>::hasValue() {
return getTry().hasValue();
}
template <class T>
bool Future<T>::hasException() {
return getTry().hasException();
}
template <class T>
void Future<T>::raise(exception_wrapper exception) {
core_->raise(std::move(exception));
......
......@@ -60,10 +60,9 @@ class Future {
!isFuture<typename std::decay<T2>::type>::value>::type>
/* implicit */ Future(T2&& val);
template <class T2 = T,
template <class T2 = T, typename =
typename std::enable_if<
folly::is_void_or_unit<T2>::value,
int>::type = 0>
folly::is_void_or_unit<T2>::value>::type>
Future();
~Future();
......@@ -111,6 +110,12 @@ class Future {
/** True when the result (or exception) is ready. */
bool isReady() const;
/// sugar for getTry().hasValue()
bool hasValue();
/// sugar for getTry().hasException()
bool hasException();
/** A reference to the Try of the value */
Try<T>& getTry();
......@@ -416,6 +421,11 @@ class Future {
auto thenMultiWithExecutor(Executor* x, Callback&& fn)
-> decltype(this->then(std::forward<Callback>(fn)));
/// Discard a result, but propagate an exception.
Future<Unit> unit() {
return then([]{ return Unit{}; });
}
protected:
typedef detail::Core<T>* corePtr;
......
......@@ -20,6 +20,8 @@
using namespace folly;
std::runtime_error eggs("eggs");
TEST(Unit, futureDefaultCtor) {
Future<Unit>();
}
......@@ -48,3 +50,29 @@ TEST(Unit, liftVoid) {
auto v = std::is_same<Unit, Lifted::type>::value;
EXPECT_TRUE(v);
}
TEST(Unit, futureToUnit) {
Future<Unit> fu = makeFuture(42).unit();
fu.value();
EXPECT_TRUE(makeFuture<int>(eggs).unit().hasException());
}
TEST(Unit, voidFutureToUnit) {
Future<Unit> fu = makeFuture().unit();
fu.value();
EXPECT_TRUE(makeFuture<void>(eggs).unit().hasException());
}
TEST(Unit, unitFutureToUnitIdentity) {
Future<Unit> fu = makeFuture(Unit{}).unit();
fu.value();
EXPECT_TRUE(makeFuture<Unit>(eggs).unit().hasException());
}
TEST(Unit, toUnitWhileInProgress) {
Promise<int> p;
Future<Unit> fu = p.getFuture().unit();
EXPECT_FALSE(fu.isReady());
p.setValue(42);
EXPECT_TRUE(fu.isReady());
}
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