/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/// needed. If your program never uses any timeouts or other time-based
/// Futures you will pay no Timekeeper thread overhead.
Future<void> sleep(Duration, Timekeeper* = nullptr);
+
+ /// 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<Z>
+ /// becomes
+ ///
+ /// f.then(chain<A,Z>(a, b, c));
+ // If anyone figures how to get chain to deduce A and Z, I'll buy you a drink.
+ template <class A, class Z, class... Callbacks>
+ std::function<Future<Z>(Try<A>)>
+ chain(Callbacks... fns);
}
template <class T>
/// value (moved out), or throws the exception.
T getVia(DrivableExecutor* e);
+ /// Unwraps the case of a Future<Future<T>> instance, and returns a simple
+ /// Future<T> instance.
+ template <class F = T>
+ typename std::enable_if<isFuture<F>::value,
+ Future<typename isFuture<T>::Inner>>::type
+ unwrap();
+
/** When this Future has completed, execute func which is a function that
takes one of:
(const) Try<T>&&
/// Variant where func is an member function
///
- /// struct Worker {
- /// R doWork(Try<T>&&); }
+ /// struct Worker { R doWork(Try<T>); }
///
/// Worker *w;
- /// Future<R> f2 = f1.then(w, &Worker::doWork);
- template <typename Caller, typename R, typename... Args>
- Future<typename isFuture<R>::Inner>
- then(Caller *instance, R(Caller::*func)(Args...));
+ /// Future<R> f2 = f1.then(&Worker::doWork, w);
+ ///
+ /// This is just sugar for
+ ///
+ /// f1.then(std::bind(&Worker::doWork, w));
+ template <typename R, typename Caller, typename... Args>
+ Future<typename isFuture<R>::Inner>
+ then(R(Caller::*func)(Args...), Caller *instance);
/// Convenience method for ignoring the value and creating a Future<void>.
/// Exceptions still propagate.
Future<T>>::type
onError(F&& func);
+ /// func is like std::function<void()> and is executed unconditionally, and
+ /// the value/exception is passed through to the resulting Future.
+ /// 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);
+
+ /// Like onError, but for timeouts. example:
+ ///
+ /// Future<int> f = makeFuture<int>(42)
+ /// .delayed(long_time)
+ /// .onTimeout(short_time,
+ /// []() -> int{ return -1; });
+ ///
+ /// or perhaps
+ ///
+ /// Future<int> f = makeFuture<int>(42)
+ /// .delayed(long_time)
+ /// .onTimeout(short_time,
+ /// []() { return makeFuture<int>(some_exception); });
+ template <class F>
+ Future<T> onTimeout(Duration, F&& func, Timekeeper* = nullptr);
+
/// This is not the method you're looking for.
///
/// This needs to be public because it's used by make* and when*, and it's
/// now. The optional Timekeeper is as with futures::sleep().
Future<T> delayed(Duration, Timekeeper* = nullptr);
- /// Block until this Future is complete. Returns a new Future containing the
- /// result.
- Future<T> wait();
+ /// Block until this Future is complete. Returns a reference to this Future.
+ Future<T>& wait() &;
+
+ /// Overload of wait() for rvalue Futures
+ Future<T>&& wait() &&;
/// Block until this Future is complete or until the given Duration passes.
- /// Returns a new Future which either contains the result or is incomplete,
- /// depending on whether the Duration passed.
- Future<T> wait(Duration);
+ /// Returns a reference to this Future
+ Future<T>& wait(Duration) &;
+
+ /// Overload of wait(Duration) for rvalue Futures
+ Future<T>&& wait(Duration) &&;
/// Call e->drive() repeatedly until the future is fulfilled. Examples
/// of DrivableExecutor include EventBase and ManualExecutor. Returns a
Future<T>& waitVia(DrivableExecutor* e) &;
/// Overload of waitVia() for rvalue Futures
- Future<T> waitVia(DrivableExecutor* e) &&;
+ Future<T>&& waitVia(DrivableExecutor* e) &&;
+
+ /// If the value in this Future is equal to the given Future, when they have
+ /// both completed, the value of the resulting Future<bool> will be true. It
+ /// will be false otherwise (including when one or both Futures have an
+ /// exception)
+ Future<bool> willEqual(Future<T>&);
- private:
+ protected:
typedef detail::Core<T>* corePtr;
// shared core state object
void throwIfInvalid() const;
friend class Promise<T>;
+ template <class> friend class Future;
// 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...>);
+
+ Executor* getExecutor() { return core_->getExecutor(); }
+ void setExecutor(Executor* x) { core_->setExecutor(x); }
};
/**
The Futures are moved in, so your copies are invalid. If you need to
chain further from these Futures, use the variant with an output iterator.
- XXX is this still true?
- This function is thread-safe for Futures running on different threads.
+ This function is thread-safe for Futures running on different threads. But
+ if you are doing anything non-trivial after, you will probably want to
+ follow with `via(executor)` because it will complete in whichever thread the
+ last Future completes in.
The return type for Future<T> input is a Future<std::vector<Try<T>>>
*/