/*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <vector>
#include <folly/Optional.h>
-#include <folly/MoveWrapper.h>
-#include <folly/futures/Deprecated.h>
+#include <folly/Portability.h>
#include <folly/futures/DrivableExecutor.h>
#include <folly/futures/Promise.h>
-#include <folly/futures/Try.h>
+#include <folly/Try.h>
#include <folly/futures/FutureException.h>
#include <folly/futures/detail/Types.h>
!isFuture<typename std::decay<T2>::type>::value>::type>
/* implicit */ Future(T2&& val);
- template <class T2 = T,
- typename std::enable_if<
- folly::is_void_or_unit<T2>::value,
- int>::type = 0>
- Future();
+ template <class T2 = T>
+ /* implicit */ Future(
+ typename std::enable_if<std::is_same<Unit, T2>::value>::type* = nullptr);
~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();
+ /// Call e->drive() repeatedly until the future is fulfilled. Examples
+ /// of DrivableExecutor include EventBase and ManualExecutor. Returns a
+ /// reference to the Try of the value.
+ Try<T>& getTryVia(DrivableExecutor* e);
+
/// If the promise has been fulfilled, return an Optional with the Try<T>.
/// Otherwise return an empty Optional.
/// Note that this moves the Try<T> out.
value(), which may rethrow if this has captured an exception. If func
throws, the exception will be captured in the Future that is returned.
*/
- /* TODO n3428 and other async frameworks have something like then(scheduler,
- Future), we might want to support a similar API which could be
- implemented a little more efficiently than
- f.via(executor).then(callback) */
- template <typename F, typename R = detail::callableResult<T, F>>
- typename R::Return then(F func) {
+ // gcc 4.8 requires that we cast function reference types to function pointer
+ // types. Fore more details see the comment on FunctionReferenceToPointer
+ // in Future-pre.h.
+ // gcc versions 4.9 and above (as well as clang) do not require this hack.
+ // For those, the FF tenplate parameter can be removed and occurences of FF
+ // replaced with F.
+ template <
+ typename F,
+ typename FF = typename detail::FunctionReferenceToPointer<F>::type,
+ typename R = detail::callableResult<T, FF>>
+ typename R::Return then(F&& func) {
typedef typename R::Arg Arguments;
- return thenImplementation<F, R>(std::move(func), Arguments());
+ return thenImplementation<FF, R>(std::forward<FF>(func), Arguments());
}
/// Variant where func is an member function
-> decltype(this->then(std::forward<Arg>(arg),
std::forward<Args>(args)...));
- /// Convenience method for ignoring the value and creating a Future<void>.
+ /// Convenience method for ignoring the value and creating a Future<Unit>.
/// Exceptions still propagate.
- Future<void> then();
+ Future<Unit> then();
/// Set an error callback for this Future. The callback should take a single
/// argument of the type that you want to catch, and should return a value of
/// func shouldn't throw, but if it does it will be captured and propagated,
/// and discard any value/exception that this Future has obtained.
template <class F>
- Future<T> ensure(F func);
+ Future<T> ensure(F&& func);
/// Like onError, but for timeouts. example:
///
/// by then), and it is active (active by default).
///
/// Inactive Futures will activate upon destruction.
- Future<T>& activate() & DEPRECATED {
+ FOLLY_DEPRECATED("do not use") Future<T>& activate() & {
core_->activate();
return *this;
}
- Future<T>& deactivate() & DEPRECATED {
+ FOLLY_DEPRECATED("do not use") Future<T>& deactivate() & {
core_->deactivate();
return *this;
}
- Future<T> activate() && DEPRECATED {
+ FOLLY_DEPRECATED("do not use") Future<T> activate() && {
core_->activate();
return std::move(*this);
}
- Future<T> deactivate() && DEPRECATED {
+ FOLLY_DEPRECATED("do not use") Future<T> deactivate() && {
core_->deactivate();
return std::move(*this);
}
template <class E>
void raise(E&& exception) {
raise(make_exception_wrapper<typename std::remove_reference<E>::type>(
- std::move(exception)));
+ std::forward<E>(exception)));
}
/// Raise an interrupt. If the promise holder has an interrupt
/// If the predicate does not obtain with the value, the result
/// is a folly::PredicateDoesNotObtain exception
template <class F>
- Future<T> filter(F predicate);
+ Future<T> filter(F&& predicate);
/// Like reduce, but works on a Future<std::vector<T / Try<T>>>, for example
/// the result of collect or collectAll
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;
template <class T2>
friend Future<T2> makeFuture(Try<T2>&&);
+ /// Repeat the given future (i.e., the computation it contains)
+ /// n times.
+ ///
+ /// thunk behaves like std::function<Future<T2>(void)>
+ template <class F>
+ friend Future<Unit> times(int n, F&& thunk);
+
+ /// Carry out the computation contained in the given future if
+ /// the predicate holds.
+ ///
+ /// thunk behaves like std::function<Future<T2>(void)>
+ template <class F>
+ friend Future<Unit> when(bool p, F&& thunk);
+
+ /// Carry out the computation contained in the given future if
+ /// while the predicate continues to hold.
+ ///
+ /// thunk behaves like std::function<Future<T2>(void)>
+ ///
+ /// predicate behaves like std::function<bool(void)>
+ template <class P, class F>
+ friend Future<Unit> whileDo(P&& predicate, F&& thunk);
+
// Variant: returns a value
// e.g. f.then([](Try<T> t){ return t.value(); });
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
- thenImplementation(F func, detail::argResult<isTry, F, Args...>);
+ thenImplementation(F&& func, detail::argResult<isTry, F, Args...>);
// Variant: returns a Future
// e.g. f.then([](Try<T> t){ return makeFuture<T>(t); });
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
- thenImplementation(F func, detail::argResult<isTry, F, Args...>);
+ thenImplementation(F&& func, detail::argResult<isTry, F, Args...>);
Executor* getExecutor() { return core_->getExecutor(); }
void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {