X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Ffutures%2FFuture.h;h=87bb0cfe417cfcc735cc39aca9ae2ced9877527d;hp=7563507d2bbc9b631a17a2a7688d850260f8d595;hb=8bedb7e1549c4a737d3ad4d7003ab9e195cd9fd9;hpb=4b7d98cb635fe2666ef0ce0d809634080eb0dcf7 diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 7563507d..87bb0cfe 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 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. @@ -53,17 +53,30 @@ class Future { Future(Future&&) noexcept; Future& operator=(Future&&) noexcept; - // conversion constructors + // converting move template < - class U, - typename = typename std::enable_if::value && - sizeof(U) == sizeof(T)>::type> - /* implicit */ Future(Future&&) noexcept; + class T2, + typename std::enable_if< + !std::is_same::type>::value && + std::is_constructible::value && + std::is_convertible::value, + int>::type = 0> + /* implicit */ Future(Future&&); template < - class U, - typename = typename std::enable_if::value && - sizeof(U) == sizeof(T)>::type> - /* implicit */ Future& operator=(Future&&) noexcept; + class T2, + typename std::enable_if< + !std::is_same::type>::value && + std::is_constructible::value && + !std::is_convertible::value, + int>::type = 0> + explicit Future(Future&&); + template < + class T2, + typename std::enable_if< + !std::is_same::type>::value && + std::is_constructible::value, + int>::type = 0> + Future& operator=(Future&&); /// Construct a Future from a value (perfect forwarding) template & 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& getTryVia(DrivableExecutor* e); + /// If the promise has been fulfilled, return an Optional with the Try. /// Otherwise return an empty Optional. /// Note that this moves the Try out. @@ -217,9 +235,12 @@ class Future { /// 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 - auto then(Executor* x, Arg&& arg, Args&&... args) - -> decltype(this->then(std::forward(arg), - std::forward(args)...)); + auto then(Executor* x, Arg&& arg, Args&&... args) { + auto oldX = getExecutor(); + setExecutor(x); + return this->then(std::forward(arg), std::forward(args)...) + .via(oldX); + } /// Convenience method for ignoring the value and creating a Future. /// Exceptions still propagate. @@ -409,14 +430,17 @@ class Future { /// /// f.thenMulti(a, b, c); template - auto thenMulti(Callback&& fn, Callbacks&&... fns) - -> decltype(this->then(std::forward(fn)). - thenMulti(std::forward(fns)...)); + auto thenMulti(Callback&& fn, Callbacks&&... fns) { + // thenMulti with two callbacks is just then(a).thenMulti(b, ...) + return then(std::forward(fn)) + .thenMulti(std::forward(fns)...); + } - // Nothing to see here, just thenMulti's base case template - auto thenMulti(Callback&& fn) - -> decltype(this->then(std::forward(fn))); + auto thenMulti(Callback&& fn) { + // thenMulti with one callback is just a then + return then(std::forward(fn)); + } /// Create a Future chain from a sequence of callbacks. i.e. /// @@ -427,14 +451,21 @@ class Future { /// /// f.thenMultiWithExecutor(executor, a, b, c); template - auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns) - -> decltype(this->then(std::forward(fn)). - thenMulti(std::forward(fns)...)); + auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns) { + // thenMultiExecutor with two callbacks is + // via(x).then(a).thenMulti(b, ...).via(oldX) + auto oldX = getExecutor(); + setExecutor(x); + return then(std::forward(fn)) + .thenMulti(std::forward(fns)...) + .via(oldX); + } - // Nothing to see here, just thenMultiWithExecutor's base case template - auto thenMultiWithExecutor(Executor* x, Callback&& fn) - -> decltype(this->then(std::forward(fn))); + auto thenMultiWithExecutor(Executor* x, Callback&& fn) { + // thenMulti with one callback is just a then with an executor + return then(x, std::forward(fn)); + } /// Discard a result, but propagate an exception. Future unit() {