#include <type_traits>
#include <vector>
-#include "folly/MoveWrapper.h"
+#include <folly/MoveWrapper.h>
#include "Promise.h"
#include "Try.h"
Future& operator=(Future const&) = delete;
// movable
- Future(Future&&);
+ Future(Future&&) noexcept;
Future& operator=(Future&&);
~Future();
typename std::add_lvalue_reference<const T>::type
value() const;
- /// Returns a future which will call back on the other side of executor.
+ /// Returns an inactive Future which will call back on the other side of
+ /// executor (when it is activated).
///
- /// f.via(e).then(a); // safe
+ /// NB remember that Futures activate when they destruct. This is good,
+ /// it means that this will work:
///
- /// f.via(e).then(a).then(b); // faux pas
+ /// f.via(e).then(a).then(b);
///
- /// a will definitely execute in the intended thread, but b may execute
- /// either in that thread, or in the current thread. If you need to
- /// guarantee where b executes, use a Later.
+ /// a and b will execute in the same context (the far side of e), because
+ /// the Future (temporary variable) created by via(e) does not call back
+ /// until it destructs, which is after then(a) and then(b) have been wired
+ /// up.
+ ///
+ /// But this is still racy:
+ ///
+ /// f = f.via(e).then(a);
+ /// f.then(b);
+ ///
+ /// If you need something like that, use a Later.
template <typename Executor>
Future<T> via(Executor* executor);
- /// Deprecated alias for via
- template <typename Executor>
- Future<T> executeWithSameThread(Executor* executor) {
- return via(executor);
- }
-
- /**
- Thread-safe version of executeWith
-
- Since an executor would likely start executing the Future chain
- right away, it would be a race condition to call:
- Future.executeWith(...).then(...), as there would be race
- condition between the then and the running Future.
- Instead, you may pass in a Promise so that we can set up
- the rest of the chain in advance, without any racey
- modifications of the continuation
-
- Deprecated. Use a Later.
- */
- template <typename Executor>
- void executeWith(Executor* executor, Promise<T>&& cont_promise);
-
/** True when the result (or exception) is ready. */
bool isReady() const;
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 probably want to support a similar API (instead of
- executeWith). */
+ Future), we might want to support a similar API which could be
+ implemented a little more efficiently than
+ f.via(executor).then(callback) */
template <class F>
typename std::enable_if<
!isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
/// Exceptions still propagate.
Future<void> then();
- /// Use of this method is advanced wizardry.
- /// XXX should this be protected?
+ /// 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
+ /// not worth listing all those and their fancy template signatures as
+ /// friends. But it's not for public consumption.
template <class F>
- void setContinuation(F&& func);
+ void setCallback_(F&& func);
+
+ /// A Future's callback is executed when all three of these conditions have
+ /// become true: it has a value (set by the Promise), it has a callback (set
+ /// by then), and it is active (active by default).
+ ///
+ /// Inactive Futures will activate upon destruction.
+ void activate() {
+ state_->activate();
+ }
+ void deactivate() {
+ state_->deactivate();
+ }
private:
- typedef detail::FutureObject<T>* objPtr;
+ typedef detail::State<T>* statePtr;
// shared state object
- objPtr obj_;
+ statePtr state_;
explicit
- Future(objPtr obj) : obj_(obj) {}
+ Future(statePtr obj) : state_(obj) {}
+
+ void detach();
void throwIfInvalid() const;
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
whenN(InputIterator first, InputIterator last, size_t n);
+/** Wait for the given future to complete on a semaphore. Returns a completed
+ * future containing the result.
+ *
+ * NB if the promise for the future would be fulfilled in the same thread that
+ * you call this, it will deadlock.
+ */
+template <class T>
+Future<T> waitWithSemaphore(Future<T>&& f);
+
+/** Wait for up to `timeout` for the given future to complete. Returns a future
+ * which may or may not be completed depending whether the given future
+ * completed in time
+ *
+ * Note: each call to this starts a (short-lived) thread and allocates memory.
+ */
+template <typename T, class Duration>
+Future<T> waitWithSemaphore(Future<T>&& f, Duration timeout);
+
}} // folly::wangle
#include "Future-inl.h"