Future& operator=(Future&&) noexcept;
/// Construct a Future from a value (perfect forwarding)
- /* implicit */
- template <class T2 = T,
- typename std::enable_if<!isFuture<T2>::value, void*>::type = nullptr>
- Future(T2&& val);
+ template <class T2 = T, typename =
+ typename std::enable_if<
+ !isFuture<typename std::decay<T2>::type>::value>::type>
+ /* implicit */ Future(T2&& val);
template <class T2 = T,
typename std::enable_if<
// The ref-qualifier allows for `this` to be moved out so we
// don't get access-after-free situations in chaining.
// https://akrzemi1.wordpress.com/2014/06/02/ref-qualifiers/
- template <typename Executor>
- Future<T> via(Executor* executor) &&;
+ inline Future<T> via(
+ Executor* executor,
+ int8_t priority = Executor::MID_PRI) &&;
/// This variant creates a new future, where the ref-qualifier && version
/// moves `this` out. This one is less efficient but avoids confusing users
/// when "return f.via(x);" fails.
- template <typename Executor>
- Future<T> via(Executor* executor) &;
+ inline Future<T> via(
+ Executor* executor,
+ int8_t priority = Executor::MID_PRI) &;
/** True when the result (or exception) is ready. */
bool isReady() const;
Future<typename isFuture<R>::Inner>
then(R(Caller::*func)(Args...), Caller *instance);
-// TODO(6838553)
-#ifndef __clang__
/// Execute the callback via the given Executor. The executor doesn't stick.
///
/// Contrast
///
/// In the former both b and c execute via x. In the latter, only b executes
/// via x, and c executes via the same executor (if any) that f had.
- template <class... Args>
- auto then(Executor* x, Args&&... args)
- -> decltype(this->then(std::forward<Args>(args)...));
-#endif
+ template <class Executor, class Arg, class... Args>
+ auto then(Executor* x, Arg&& arg, Args&&... args)
+ -> decltype(this->then(std::forward<Arg>(arg),
+ std::forward<Args>(args)...));
/// Convenience method for ignoring the value and creating a Future<void>.
/// Exceptions still propagate.
/// by then), and it is active (active by default).
///
/// Inactive Futures will activate upon destruction.
- Future<T>& activate() & {
+ Future<T>& activate() & DEPRECATED {
core_->activate();
return *this;
}
- Future<T>& deactivate() & {
+ Future<T>& deactivate() & DEPRECATED {
core_->deactivate();
return *this;
}
- Future<T> activate() && {
+ Future<T> activate() && DEPRECATED {
core_->activate();
return std::move(*this);
}
- Future<T> deactivate() && {
+ Future<T> deactivate() && DEPRECATED {
core_->deactivate();
return std::move(*this);
}
template <class F>
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
+ template <class I, class F>
+ Future<I> reduce(I&& initial, F&& func);
+
+ /// Create a Future chain from a sequence of callbacks. i.e.
+ ///
+ /// f.then(a).then(b).then(c)
+ ///
+ /// where f is a Future<A> and the result of the chain is a Future<D>
+ /// becomes
+ ///
+ /// f.thenMulti(a, b, c);
+ template <class Callback, class... Callbacks>
+ auto thenMulti(Callback&& fn, Callbacks&&... fns)
+ -> decltype(this->then(std::forward<Callback>(fn)).
+ thenMulti(std::forward<Callbacks>(fns)...));
+
+ // Nothing to see here, just thenMulti's base case
+ template <class Callback>
+ auto thenMulti(Callback&& fn)
+ -> decltype(this->then(std::forward<Callback>(fn)));
+
+ /// Create a Future chain from a sequence of callbacks. i.e.
+ ///
+ /// f.via(executor).then(a).then(b).then(c).via(oldExecutor)
+ ///
+ /// where f is a Future<A> and the result of the chain is a Future<D>
+ /// becomes
+ ///
+ /// f.thenMultiWithExecutor(executor, a, b, c);
+ template <class Callback, class... Callbacks>
+ auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns)
+ -> decltype(this->then(std::forward<Callback>(fn)).
+ thenMulti(std::forward<Callbacks>(fns)...));
+
+ // Nothing to see here, just thenMultiWithExecutor's base case
+ template <class Callback>
+ auto thenMultiWithExecutor(Executor* x, Callback&& fn)
+ -> decltype(this->then(std::forward<Callback>(fn)));
+
protected:
typedef detail::Core<T>* corePtr;
friend class Promise<T>;
template <class> friend class Future;
+ template <class T2>
+ friend Future<T2> makeFuture(Try<T2>&&);
+
// Variant: returns a value
// e.g. f.then([](Try<T> t){ return t.value(); });
template <typename F, typename R, bool isTry, typename... Args>
thenImplementation(F func, detail::argResult<isTry, F, Args...>);
Executor* getExecutor() { return core_->getExecutor(); }
- void setExecutor(Executor* x) { core_->setExecutor(x); }
+ void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {
+ core_->setExecutor(x, priority);
+ }
};
-
} // folly
#include <folly/futures/Future-inl.h>