From: Hans Fugal Date: Wed, 1 Jul 2015 22:42:23 +0000 (-0700) Subject: Nuke Future (folly/futures) X-Git-Tag: v0.49.0~13 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=e845ef57f1f368944123e4a50bd4d1616a363efa Nuke Future (folly/futures) Summary: Nuke Future in favor of Future, for the `folly/futures` subdirectory. Reviewed By: @djwatson Differential Revision: D2201259 --- diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h index 9cacf19d..0595310a 100644 --- a/folly/futures/Future-inl.h +++ b/folly/futures/Future-inl.h @@ -51,7 +51,7 @@ Future::Future(T2&& val) template template Future::Future() - : core_(new detail::Core(Try())) {} + : core_(new detail::Core(Try(T()))) {} template Future::~Future() { @@ -226,7 +226,7 @@ auto Future::then(Executor* x, Arg&& arg, Args&&... args) } template -Future Future::then() { +Future Future::then() { return then([] () {}); } @@ -432,8 +432,6 @@ inline Future Future::via(Executor* executor, int8_t priority) & { template auto via(Executor* x, Func func) -> Future::Inner> -// this would work, if not for Future :-/ -// -> decltype(via(x).then(func)) { // TODO make this actually more performant. :-P #7260175 return via(x).then(func); @@ -468,24 +466,29 @@ Future::type> makeFuture(T&& t) { } inline // for multiple translation units -Future makeFuture() { - return makeFuture(Try()); +Future makeFuture() { + return makeFuture(Unit{}); } +// XXX why is the dual necessary here? Can't we just use perfect forwarding +// and capture func by reference always? template auto makeFutureWith( F&& func, typename std::enable_if::value, bool>::type sdf) - -> Future { - return makeFuture(makeTryWith([&func]() { + -> Future::type> { + using LiftedResult = typename Unit::Lift::type; + return makeFuture(makeTryWith([&func]() { return (func)(); })); } template -auto makeFutureWith(F const& func) -> Future { +auto makeFutureWith(F const& func) + -> Future::type> { F copy = func; - return makeFuture(makeTryWith(std::move(copy))); + using LiftedResult = typename Unit::Lift::type; + return makeFuture(makeTryWith(std::move(copy))); } template @@ -511,7 +514,7 @@ Future makeFuture(Try&& t) { } // via -Future via(Executor* executor, int8_t priority) { +Future via(Executor* executor, int8_t priority) { return makeFuture().via(executor, priority); } @@ -603,14 +606,6 @@ struct CollectContext { std::atomic threw {false}; }; -// Specialize for void (implementations in Future.cpp) - -template <> -CollectContext::~CollectContext(); - -template <> -void CollectContext::setPartialResult(size_t i, Try& t); - } template @@ -884,7 +879,7 @@ Future Future::within(Duration dur, E e, Timekeeper* tk) { } tk->after(dur) - .then([ctx](Try const& t) { + .then([ctx](Try const& t) { if (ctx->token.exchange(true) == false) { if (t.hasException()) { ctx->promise.setException(std::move(t.exception())); @@ -908,7 +903,7 @@ Future Future::within(Duration dur, E e, Timekeeper* tk) { template Future Future::delayed(Duration dur, Timekeeper* tk) { return collectAll(*this, futures::sleep(dur, tk)) - .then([](std::tuple, Try> tup) { + .then([](std::tuple, Try> tup) { Try& t = std::get<0>(tup); return makeFuture(std::move(t)); }); @@ -1007,11 +1002,6 @@ T Future::get() { return std::move(wait().value()); } -template <> -inline void Future::get() { - wait().value(); -} - template T Future::get(Duration dur) { wait(dur); @@ -1022,26 +1012,11 @@ T Future::get(Duration dur) { } } -template <> -inline void Future::get(Duration dur) { - wait(dur); - if (isReady()) { - return; - } else { - throw TimedOut(); - } -} - template T Future::getVia(DrivableExecutor* e) { return std::move(waitVia(e).value()); } -template <> -inline void Future::getVia(DrivableExecutor* e) { - waitVia(e).value(); -} - namespace detail { template struct TryEquals { @@ -1049,13 +1024,6 @@ namespace detail { return t1.value() == t2.value(); } }; - - template <> - struct TryEquals { - static bool equals(const Try& t1, const Try& t2) { - return true; - } - }; } template @@ -1134,7 +1102,7 @@ namespace futures { } // Instantiate the most common Future types to save compile time -extern template class Future; +extern template class Future; extern template class Future; extern template class Future; extern template class Future; @@ -1142,8 +1110,3 @@ extern template class Future; extern template class Future; } // namespace folly - -// I haven't included a Future specialization because I don't forsee us -// using it, however it is not difficult to add when needed. Refer to -// Future for guidance. std::future and boost::future code would also be -// instructive. diff --git a/folly/futures/Future-pre.h b/folly/futures/Future-pre.h index f76c24ab..f1a07d5d 100644 --- a/folly/futures/Future-pre.h +++ b/folly/futures/Future-pre.h @@ -24,7 +24,7 @@ template class Promise; template struct isFuture : std::false_type { - typedef T Inner; + using Inner = typename Unit::Lift::type; }; template @@ -63,7 +63,7 @@ struct ArgType<> { template struct argResult { - typedef resultOf Result; + using Result = resultOf; }; template @@ -100,19 +100,6 @@ struct callableResult { typedef Future Return; }; -template -struct callableResult { - typedef typename std::conditional< - callableWith::value, - detail::argResult, - typename std::conditional< - callableWith&&>::value, - detail::argResult&&>, - detail::argResult&>>::type>::type Arg; - typedef isFuture ReturnsFuture; - typedef Future Return; -}; - template struct Extract : Extract { }; diff --git a/folly/futures/Future.cpp b/folly/futures/Future.cpp index 78f33d26..e4265ebc 100644 --- a/folly/futures/Future.cpp +++ b/folly/futures/Future.cpp @@ -20,7 +20,7 @@ namespace folly { // Instantiate the most common Future types to save compile time -template class Future; +template class Future; template class Future; template class Future; template class Future; @@ -31,7 +31,7 @@ template class Future; namespace folly { namespace futures { -Future sleep(Duration dur, Timekeeper* tk) { +Future sleep(Duration dur, Timekeeper* tk) { if (LIKELY(!tk)) { tk = detail::getTimekeeperSingleton(); } @@ -39,19 +39,3 @@ Future sleep(Duration dur, Timekeeper* tk) { } }} - -namespace folly { namespace detail { - -template <> -CollectContext::~CollectContext() { - if (!threw.exchange(true)) { - p.setValue(); - } -} - -template <> -void CollectContext::setPartialResult(size_t i, Try& t) { - // Nothing to do for void -} - -}} diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 649cd667..a1f78262 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -62,7 +62,7 @@ class Future { template ::value>::type> + std::is_same::value>::type> Future(); ~Future(); @@ -202,9 +202,9 @@ class Future { -> decltype(this->then(std::forward(arg), std::forward(args)...)); - /// Convenience method for ignoring the value and creating a Future. + /// Convenience method for ignoring the value and creating a Future. /// Exceptions still propagate. - Future then(); + Future 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 diff --git a/folly/futures/Promise.h b/folly/futures/Promise.h index c6af9168..88f6631f 100644 --- a/folly/futures/Promise.h +++ b/folly/futures/Promise.h @@ -70,13 +70,6 @@ public: /// handled. void setInterruptHandler(std::function); - /// Fulfill this Promise - template - typename std::enable_if::value, void>::type - setValue() { - setTry(Try()); - } - /// Sugar to fulfill this Promise template typename std::enable_if::value, void>::type diff --git a/folly/futures/SharedPromise.h b/folly/futures/SharedPromise.h index 0c8fcd9a..1d5670cd 100644 --- a/folly/futures/SharedPromise.h +++ b/folly/futures/SharedPromise.h @@ -81,13 +81,6 @@ public: /// handled. void setInterruptHandler(std::function); - /// Fulfill this SharedPromise - template - typename std::enable_if::value, void>::type - setValue() { - setTry(Try()); - } - /// Sugar to fulfill this SharedPromise template typename std::enable_if::value, void>::type diff --git a/folly/futures/Timekeeper.h b/folly/futures/Timekeeper.h index 3612f5cf..3e3e20a7 100644 --- a/folly/futures/Timekeeper.h +++ b/folly/futures/Timekeeper.h @@ -17,13 +17,14 @@ #pragma once #include +#include namespace folly { template class Future; /// A Timekeeper handles the details of keeping time and fulfilling delay -/// promises. The returned Future will either complete after the +/// promises. The returned Future will either complete after the /// elapsed time, or in the event of some kind of exceptional error may hold /// an exception. These Futures respond to cancellation. If you use a lot of /// Delays and many of them ultimately are unneeded (as would be the case for @@ -34,7 +35,7 @@ template class Future; /// use them implicitly behind the scenes by passing a timeout to some Future /// operation. /// -/// Although we don't formally alias Delay = Future, +/// Although we don't formally alias Delay = Future, /// that's an appropriate term for it. People will probably also call these /// Timeouts, and that's ok I guess, but that term is so overloaded I thought /// it made sense to introduce a cleaner term. @@ -54,7 +55,7 @@ class Timekeeper { /// This future probably completes on the timer thread. You should almost /// certainly follow it with a via() call or the accuracy of other timers /// will suffer. - virtual Future after(Duration) = 0; + virtual Future after(Duration) = 0; /// Returns a future that will complete at the requested time. /// @@ -65,7 +66,7 @@ class Timekeeper { /// the system clock but rather execute that many milliseconds in the future /// according to the steady clock. template - Future at(std::chrono::time_point when); + Future at(std::chrono::time_point when); }; } // namespace folly @@ -77,7 +78,7 @@ class Timekeeper { namespace folly { template -Future Timekeeper::at(std::chrono::time_point when) { +Future Timekeeper::at(std::chrono::time_point when) { auto now = Clock::now(); if (when <= now) { diff --git a/folly/futures/Try-inl.h b/folly/futures/Try-inl.h index fac9cc56..05f384a8 100644 --- a/folly/futures/Try-inl.h +++ b/folly/futures/Try-inl.h @@ -31,6 +31,21 @@ Try::Try(Try&& t) noexcept : contains_(t.contains_) { } } +template +template +Try::Try(typename std::enable_if::value, + Try const&>::type t) + : contains_(Contains::NOTHING) { + if (t.hasValue()) { + contains_ = Contains::VALUE; + new (&value_) T(); + } else if (t.hasException()) { + contains_ = Contains::EXCEPTION; + new (&e_) std::unique_ptr( + folly::make_unique(t.exception())); + } +} + template Try& Try::operator=(Try&& t) noexcept { if (this == &t) { diff --git a/folly/futures/Try.h b/folly/futures/Try.h index 5f5f634b..d06d5b62 100644 --- a/folly/futures/Try.h +++ b/folly/futures/Try.h @@ -35,8 +35,7 @@ namespace folly { * context. Exceptions are stored as exception_wrappers so that the user can * minimize rethrows if so desired. * - * There is a specialization, Try, which represents either success - * or an exception. + * To represent success or a captured exception, use Try */ template class Try { @@ -74,6 +73,12 @@ class Try { */ explicit Try(T&& v) : contains_(Contains::VALUE), value_(std::move(v)) {} + /// Implicit conversion from Try to Try + template + /* implicit */ + Try(typename std::enable_if::value, + Try const&>::type t); + /* * Construct a Try with an exception_wrapper * @@ -364,7 +369,7 @@ typename std::enable_if< makeTryWith(F&& f); /* - * Specialization of makeTryWith for void + * Specialization of makeTryWith for void return * * @param f a function to execute and capture the result of * diff --git a/folly/futures/Unit.h b/folly/futures/Unit.h index 44c3661b..d4d99d67 100644 --- a/folly/futures/Unit.h +++ b/folly/futures/Unit.h @@ -22,8 +22,6 @@ namespace folly { /// metaprogramming. So, instead of e.g. Future, we have Future. /// You can ignore the actual value, and we port some of the syntactic /// niceties like setValue() instead of setValue(Unit{}). -// We will soon return Future wherever we currently return Future -// #6847876 struct Unit { /// Lift type T into Unit. This is the definition for all non-void types. template struct Lift : public std::false_type { diff --git a/folly/futures/detail/ThreadWheelTimekeeper.cpp b/folly/futures/detail/ThreadWheelTimekeeper.cpp index 8b5745d6..cd10671b 100644 --- a/folly/futures/detail/ThreadWheelTimekeeper.cpp +++ b/folly/futures/detail/ThreadWheelTimekeeper.cpp @@ -32,13 +32,13 @@ namespace { return new WTCallback(base); } - Future getFuture() { + Future getFuture() { return promise_.getFuture(); } protected: EventBase* base_; - Promise promise_; + Promise promise_; explicit WTCallback(EventBase* base) : base_(base) { @@ -81,7 +81,7 @@ ThreadWheelTimekeeper::~ThreadWheelTimekeeper() { thread_.join(); } -Future ThreadWheelTimekeeper::after(Duration dur) { +Future ThreadWheelTimekeeper::after(Duration dur) { auto cob = WTCallback::create(&eventBase_); auto f = cob->getFuture(); eventBase_.runInEventBaseThread([=]{ diff --git a/folly/futures/detail/ThreadWheelTimekeeper.h b/folly/futures/detail/ThreadWheelTimekeeper.h index ddbb442d..9625de78 100644 --- a/folly/futures/detail/ThreadWheelTimekeeper.h +++ b/folly/futures/detail/ThreadWheelTimekeeper.h @@ -37,7 +37,7 @@ class ThreadWheelTimekeeper : public Timekeeper { /// This future *does* complete on the timer thread. You should almost /// certainly follow it with a via() call or the accuracy of other timers /// will suffer. - Future after(Duration) override; + Future after(Duration) override; protected: folly::EventBase eventBase_; diff --git a/folly/futures/helpers.h b/folly/futures/helpers.h index c099f580..0d0b881c 100644 --- a/folly/futures/helpers.h +++ b/folly/futures/helpers.h @@ -37,7 +37,7 @@ namespace futures { /// The Timekeeper thread will be lazily created the first time it is /// needed. If your program never uses any timeouts or other time-based /// Futures you will pay no Timekeeper thread overhead. - Future sleep(Duration, Timekeeper* = nullptr); + Future sleep(Duration, Timekeeper* = nullptr); /** * Set func as the callback for each input Future and return a vector of @@ -72,21 +72,19 @@ template Future::type> makeFuture(T&& t); /** Make a completed void Future. */ -Future makeFuture(); +Future makeFuture(); /** Make a completed Future by executing a function. If the function throws we capture the exception, otherwise we capture the result. */ template auto makeFutureWith( - F&& func, - typename std::enable_if< - !std::is_reference::value, bool>::type sdf = false) - -> Future; + F&& func, + typename std::enable_if::value, bool>::type sdf) + -> Future::type>; template -auto makeFutureWith( - F const& func) - -> Future; +auto makeFutureWith(F const& func) + -> Future::type>; /// Make a failed Future from an exception_ptr. /// Because the Future's type cannot be inferred you have to specify it, e.g. @@ -120,7 +118,7 @@ Future makeFuture(Try&& t); * * @returns a void Future that will call back on the given executor */ -inline Future via( +inline Future via( Executor* executor, int8_t priority = Executor::MID_PRI); diff --git a/folly/futures/test/Benchmark.cpp b/folly/futures/test/Benchmark.cpp index 8721622b..61518326 100644 --- a/folly/futures/test/Benchmark.cpp +++ b/folly/futures/test/Benchmark.cpp @@ -170,8 +170,8 @@ BENCHMARK_DRAW_LINE(); // The old way. Throw an exception, and rethrow to access it upstream. void throwAndCatchImpl() { makeFuture() - .then([](Try&&){ throw std::runtime_error("oh no"); }) - .then([](Try&& t) { + .then([](Try&&){ throw std::runtime_error("oh no"); }) + .then([](Try&& t) { try { t.value(); } catch(const std::runtime_error& e) { @@ -190,8 +190,8 @@ void throwAndCatchImpl() { // will try to wrap, so no exception_ptrs/rethrows are necessary. void throwAndCatchWrappedImpl() { makeFuture() - .then([](Try&&){ throw std::runtime_error("oh no"); }) - .then([](Try&& t) { + .then([](Try&&){ throw std::runtime_error("oh no"); }) + .then([](Try&& t) { auto caught = t.withException( [](const std::runtime_error& e){ // ... @@ -203,10 +203,10 @@ void throwAndCatchWrappedImpl() { // Better. Wrap an exception, and rethrow to access it upstream. void throwWrappedAndCatchImpl() { makeFuture() - .then([](Try&&){ - return makeFuture(std::runtime_error("oh no")); + .then([](Try&&){ + return makeFuture(std::runtime_error("oh no")); }) - .then([](Try&& t) { + .then([](Try&& t) { try { t.value(); } catch(const std::runtime_error& e) { @@ -220,10 +220,10 @@ void throwWrappedAndCatchImpl() { // The new way. Wrap an exception, and access it via the wrapper upstream void throwWrappedAndCatchWrappedImpl() { makeFuture() - .then([](Try&&){ - return makeFuture(std::runtime_error("oh no")); + .then([](Try&&){ + return makeFuture(std::runtime_error("oh no")); }) - .then([](Try&& t){ + .then([](Try&& t){ auto caught = t.withException( [](const std::runtime_error& e){ // ... diff --git a/folly/futures/test/CollectTest.cpp b/folly/futures/test/CollectTest.cpp index f9746d18..5834f228 100644 --- a/folly/futures/test/CollectTest.cpp +++ b/folly/futures/test/CollectTest.cpp @@ -87,14 +87,14 @@ TEST(Collect, collectAll) { // check that futures are ready in then() { - std::vector> promises(10); - std::vector> futures; + std::vector> promises(10); + std::vector> futures; for (auto& p : promises) futures.push_back(p.getFuture()); auto allf = collectAll(futures) - .then([](Try>>&& ts) { + .then([](Try>>&& ts) { for (auto& f : ts.value()) f.value(); }); @@ -166,8 +166,8 @@ TEST(Collect, collect) { // void futures success case { - std::vector> promises(10); - std::vector> futures; + std::vector> promises(10); + std::vector> futures; for (auto& p : promises) futures.push_back(p.getFuture()); @@ -185,8 +185,8 @@ TEST(Collect, collect) { // void futures failure case { - std::vector> promises(10); - std::vector> futures; + std::vector> promises(10); + std::vector> futures; for (auto& p : promises) futures.push_back(p.getFuture()); @@ -294,8 +294,8 @@ TEST(Collect, collectAny) { // error { - std::vector> promises(10); - std::vector> futures; + std::vector> promises(10); + std::vector> futures; for (auto& p : promises) futures.push_back(p.getFuture()); @@ -334,12 +334,12 @@ TEST(Collect, collectAny) { TEST(Collect, alreadyCompleted) { { - std::vector> fs; + std::vector> fs; for (int i = 0; i < 10; i++) fs.push_back(makeFuture()); collectAll(fs) - .then([&](std::vector> ts) { + .then([&](std::vector> ts) { EXPECT_EQ(fs.size(), ts.size()); }); } @@ -484,8 +484,8 @@ TEST(Collect, allParallelWithError) { } TEST(Collect, collectN) { - std::vector> promises(10); - std::vector> futures; + std::vector> promises(10); + std::vector> futures; for (auto& p : promises) futures.push_back(p.getFuture()); @@ -493,7 +493,7 @@ TEST(Collect, collectN) { bool flag = false; size_t n = 3; collectN(futures, n) - .then([&](std::vector>> v) { + .then([&](std::vector>> v) { flag = true; EXPECT_EQ(n, v.size()); for (auto& tt : v) @@ -510,13 +510,13 @@ TEST(Collect, collectN) { /// Ensure that we can compile collectAll/Any with folly::small_vector TEST(Collect, smallVector) { - static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future), + static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future), "Futures should not be trivially copyable"); static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future), "Futures should not be trivially copyable"); { - folly::small_vector> futures; + folly::small_vector> futures; for (int i = 0; i < 10; i++) futures.push_back(makeFuture()); @@ -524,7 +524,7 @@ TEST(Collect, smallVector) { auto anyf = collectAny(futures); } { - folly::small_vector> futures; + folly::small_vector> futures; for (int i = 0; i < 10; i++) futures.push_back(makeFuture()); diff --git a/folly/futures/test/ContextTest.cpp b/folly/futures/test/ContextTest.cpp index 487753aa..1e09a3a1 100644 --- a/folly/futures/test/ContextTest.cpp +++ b/folly/futures/test/ContextTest.cpp @@ -40,7 +40,7 @@ TEST(Context, basic) { std::unique_ptr(new TestData(10))); // Start a future - Promise p; + Promise p; auto future = p.getFuture().then([&]{ // Check that the context followed the future EXPECT_TRUE(RequestContext::get() != nullptr); diff --git a/folly/futures/test/CoreTest.cpp b/folly/futures/test/CoreTest.cpp index 7e2ad647..dedfeec3 100644 --- a/folly/futures/test/CoreTest.cpp +++ b/folly/futures/test/CoreTest.cpp @@ -24,5 +24,5 @@ using namespace folly; TEST(Core, size) { // If this number goes down, it's fine! // If it goes up, please seek professional advice ;-) - EXPECT_EQ(192, sizeof(detail::Core)); + EXPECT_EQ(192, sizeof(detail::Core)); } diff --git a/folly/futures/test/ExecutorTest.cpp b/folly/futures/test/ExecutorTest.cpp index c7b06dd6..0f0fe183 100644 --- a/folly/futures/test/ExecutorTest.cpp +++ b/folly/futures/test/ExecutorTest.cpp @@ -95,7 +95,7 @@ TEST(ManualExecutor, waitForDoesNotDeadlock) { folly::Baton<> baton; auto f = makeFuture() .via(&east) - .then([](Try){ return makeFuture(); }) + .then([](Try){ return makeFuture(); }) .via(&west); std::thread t([&]{ baton.post(); @@ -162,7 +162,7 @@ TEST(Executor, RunnablePtr) { TEST(Executor, ThrowableThen) { InlineExecutor x; - auto f = Future().via(&x).then([](){ + auto f = Future().via(&x).then([](){ throw std::runtime_error("Faildog"); }); EXPECT_THROW(f.value(), std::exception); diff --git a/folly/futures/test/FutureTest.cpp b/folly/futures/test/FutureTest.cpp index d6e1990c..16c9f1f9 100644 --- a/folly/futures/test/FutureTest.cpp +++ b/folly/futures/test/FutureTest.cpp @@ -320,11 +320,11 @@ TEST(Future, thenTry) { .then([&](Try&& t) { flag = true; EXPECT_EQ(42, t.value()); }); EXPECT_TRUE(flag); flag = false; - makeFuture().then([&](Try&& t) { flag = true; t.value(); }); + makeFuture().then([&](Try&& t) { flag = true; t.value(); }); EXPECT_TRUE(flag); flag = false; - Promise p; - auto f = p.getFuture().then([&](Try&& t) { flag = true; }); + Promise p; + auto f = p.getFuture().then([&](Try&& t) { flag = true; }); EXPECT_FALSE(flag); EXPECT_FALSE(f.isReady()); p.setValue(); @@ -353,7 +353,7 @@ TEST(Future, thenValue) { auto f = makeFuture(eggs).then([&](int i){}); EXPECT_THROW(f.value(), eggs_t); - f = makeFuture(eggs).then([&]{}); + f = makeFuture(eggs).then([&]{}); EXPECT_THROW(f.value(), eggs_t); } @@ -366,7 +366,7 @@ TEST(Future, thenValueFuture) { makeFuture() .then([]{ return makeFuture(); }) - .then([&](Try&& t) { flag = true; }); + .then([&](Try&& t) { flag = true; }); EXPECT_TRUE(flag); flag = false; } @@ -505,7 +505,7 @@ TEST(Future, makeFuture) { EXPECT_TYPE(makeFutureWith(failfun), Future); EXPECT_THROW(makeFutureWith(failfun).value(), eggs_t); - EXPECT_TYPE(makeFuture(), Future); + EXPECT_TYPE(makeFuture(), Future); } TEST(Future, finish) { @@ -568,18 +568,18 @@ TEST(Future, unwrap) { TEST(Future, throwCaughtInImmediateThen) { // Neither of these should throw "Promise already satisfied" makeFuture().then( - [=](Try&&) -> int { throw std::exception(); }); + [=](Try&&) -> int { throw std::exception(); }); makeFuture().then( - [=](Try&&) -> Future { throw std::exception(); }); + [=](Try&&) -> Future { throw std::exception(); }); } TEST(Future, throwIfFailed) { - makeFuture(eggs) - .then([=](Try&& t) { + makeFuture(eggs) + .then([=](Try&& t) { EXPECT_THROW(t.throwIfFailed(), eggs_t); }); makeFuture() - .then([=](Try&& t) { + .then([=](Try&& t) { EXPECT_NO_THROW(t.throwIfFailed()); }); @@ -600,7 +600,7 @@ TEST(Future, getFutureAfterSetValue) { } TEST(Future, getFutureAfterSetException) { - Promise p; + Promise p; p.setWith([]() -> void { throw std::logic_error("foo"); }); EXPECT_THROW(p.getFuture().value(), std::logic_error); } @@ -655,7 +655,7 @@ TEST(Future, CircularDependencySharedPtrSelfReset) { TEST(Future, Constructor) { auto f1 = []() -> Future { return Future(3); }(); EXPECT_EQ(f1.value(), 3); - auto f2 = []() -> Future { return Future(); }(); + auto f2 = []() -> Future { return Future(); }(); EXPECT_NO_THROW(f2.value()); } @@ -664,7 +664,7 @@ TEST(Future, ImplicitConstructor) { EXPECT_EQ(f1.value(), 3); // Unfortunately, the C++ standard does not allow the // following implicit conversion to work: - //auto f2 = []() -> Future { }(); + //auto f2 = []() -> Future { }(); } TEST(Future, thenDynamic) { @@ -734,3 +734,7 @@ TEST(Future, RequestContext) { p1.setValue(3); p2.setValue(4); } + +TEST(Future, makeFutureNoThrow) { + makeFuture().value(); +} diff --git a/folly/futures/test/InterruptTest.cpp b/folly/futures/test/InterruptTest.cpp index 1963c0a7..99f8b696 100644 --- a/folly/futures/test/InterruptTest.cpp +++ b/folly/futures/test/InterruptTest.cpp @@ -23,7 +23,7 @@ using namespace folly; TEST(Interrupt, raise) { std::runtime_error eggs("eggs"); - Promise p; + Promise p; p.setInterruptHandler([&](const exception_wrapper& e) { EXPECT_THROW(e.throwException(), decltype(eggs)); }); @@ -31,7 +31,7 @@ TEST(Interrupt, raise) { } TEST(Interrupt, cancel) { - Promise p; + Promise p; p.setInterruptHandler([&](const exception_wrapper& e) { EXPECT_THROW(e.throwException(), FutureCancellation); }); @@ -55,7 +55,7 @@ TEST(Interrupt, interruptThenHandle) { } TEST(Interrupt, interruptAfterFulfilNoop) { - Promise p; + Promise p; bool flag = false; p.setInterruptHandler([&](const exception_wrapper& e) { flag = true; }); p.setValue(); @@ -64,7 +64,7 @@ TEST(Interrupt, interruptAfterFulfilNoop) { } TEST(Interrupt, secondInterruptNoop) { - Promise p; + Promise p; int count = 0; p.setInterruptHandler([&](const exception_wrapper& e) { count++; }); auto f = p.getFuture(); diff --git a/folly/futures/test/MapTest.cpp b/folly/futures/test/MapTest.cpp index ed0313d7..ec75bf82 100644 --- a/folly/futures/test/MapTest.cpp +++ b/folly/futures/test/MapTest.cpp @@ -31,7 +31,7 @@ TEST(Map, basic) { fs.push_back(p3.getFuture()); int c = 0; - std::vector> fs2 = futures::map(fs, [&](int i){ + std::vector> fs2 = futures::map(fs, [&](int i){ c += i; }); diff --git a/folly/futures/test/PollTest.cpp b/folly/futures/test/PollTest.cpp index 166dea67..d241b4e4 100644 --- a/folly/futures/test/PollTest.cpp +++ b/folly/futures/test/PollTest.cpp @@ -34,7 +34,7 @@ TEST(Poll, notReady) { } TEST(Poll, exception) { - Promise p; + Promise p; auto f = p.getFuture(); p.setWith([] { throw std::runtime_error("Runtime"); }); EXPECT_TRUE(f.poll().value().hasException()); diff --git a/folly/futures/test/PromiseTest.cpp b/folly/futures/test/PromiseTest.cpp index 5e207068..6338d685 100644 --- a/folly/futures/test/PromiseTest.cpp +++ b/folly/futures/test/PromiseTest.cpp @@ -70,7 +70,7 @@ TEST(Promise, setValue) { unique_ptr ptr = std::move(fmov.value()); EXPECT_EQ(42, *ptr); - Promise v; + Promise v; auto fv = v.getFuture(); v.setValue(); EXPECT_TRUE(fv.isReady()); @@ -78,13 +78,13 @@ TEST(Promise, setValue) { TEST(Promise, setException) { { - Promise p; + Promise p; auto f = p.getFuture(); p.setException(eggs); EXPECT_THROW(f.value(), eggs_t); } { - Promise p; + Promise p; auto f = p.getFuture(); try { throw eggs; diff --git a/folly/futures/test/TimekeeperTest.cpp b/folly/futures/test/TimekeeperTest.cpp index d913b70d..4c500cb5 100644 --- a/folly/futures/test/TimekeeperTest.cpp +++ b/folly/futures/test/TimekeeperTest.cpp @@ -123,7 +123,7 @@ TEST(Timekeeper, futureWithinVoidSpecialization) { } TEST(Timekeeper, futureWithinException) { - Promise p; + Promise p; auto f = p.getFuture().within(awhile, std::runtime_error("expected")); EXPECT_THROW(f.get(), std::runtime_error); } @@ -150,7 +150,7 @@ TEST(Timekeeper, onTimeoutVoid) { }); makeFuture().delayed(one_ms) .onTimeout(Duration(0), [&]{ - return makeFuture(std::runtime_error("expected")); + return makeFuture(std::runtime_error("expected")); }); // just testing compilation here } diff --git a/folly/futures/test/TryTest.cpp b/folly/futures/test/TryTest.cpp index 479fcb99..cc111c1c 100644 --- a/folly/futures/test/TryTest.cpp +++ b/folly/futures/test/TryTest.cpp @@ -36,7 +36,7 @@ TEST(Try, basic) { A a(5); Try t_a(std::move(a)); - Try t_void; + Try t_void; EXPECT_EQ(5, t_a.value().x()); } diff --git a/folly/futures/test/UnitTest.cpp b/folly/futures/test/UnitTest.cpp index 7e09a10b..e4ef1eb9 100644 --- a/folly/futures/test/UnitTest.cpp +++ b/folly/futures/test/UnitTest.cpp @@ -35,7 +35,7 @@ TEST(Unit, operatorNe) { } TEST(Unit, voidOrUnit) { - EXPECT_TRUE(is_void_or_unit::value); + EXPECT_TRUE(is_void_or_unit::value); EXPECT_TRUE(is_void_or_unit::value); EXPECT_FALSE(is_void_or_unit::value); } @@ -53,7 +53,7 @@ TEST(Unit, liftInt) { } TEST(Unit, liftVoid) { - using Lifted = Unit::Lift; + using Lifted = Unit::Lift; EXPECT_TRUE(Lifted::value); auto v = std::is_same::value; EXPECT_TRUE(v); @@ -68,7 +68,7 @@ TEST(Unit, futureToUnit) { TEST(Unit, voidFutureToUnit) { Future fu = makeFuture().unit(); fu.value(); - EXPECT_TRUE(makeFuture(eggs).unit().hasException()); + EXPECT_TRUE(makeFuture(eggs).unit().hasException()); } TEST(Unit, unitFutureToUnitIdentity) { @@ -84,3 +84,9 @@ TEST(Unit, toUnitWhileInProgress) { p.setValue(42); EXPECT_TRUE(fu.isReady()); } + +TEST(Unit, makeFutureWith) { + int count = 0; + Future fu = makeFutureWith([&]{ count++; }); + EXPECT_EQ(1, count); +} diff --git a/folly/futures/test/ViaTest.cpp b/folly/futures/test/ViaTest.cpp index 5027ed91..6408ee3f 100644 --- a/folly/futures/test/ViaTest.cpp +++ b/folly/futures/test/ViaTest.cpp @@ -124,7 +124,7 @@ TEST(Via, thenFunction) { TEST_F(ViaFixture, threadHops) { auto westThreadId = std::this_thread::get_id(); - auto f = via(eastExecutor.get()).then([=](Try&& t) { + auto f = via(eastExecutor.get()).then([=](Try&& t) { EXPECT_NE(std::this_thread::get_id(), westThreadId); return makeFuture(1); }).via(westExecutor.get() @@ -283,7 +283,7 @@ TEST(Via, then2) { } TEST(Via, then2Variadic) { - struct Foo { bool a = false; void foo(Try) { a = true; } }; + struct Foo { bool a = false; void foo(Try) { a = true; } }; Foo f; ManualExecutor x; makeFuture().then(&x, &Foo::foo, &f); @@ -345,14 +345,14 @@ TEST(Via, callbackRace) { ThreadExecutor x; auto fn = [&x]{ - auto promises = std::make_shared>>(4); - std::vector> futures; + auto promises = std::make_shared>>(4); + std::vector> futures; for (auto& p : *promises) { futures.emplace_back( p.getFuture() .via(&x) - .then([](Try&&){})); + .then([](Try&&){})); } x.waitForStartup(); @@ -424,16 +424,16 @@ TEST(Via, waitVia) { TEST(Via, viaRaces) { ManualExecutor x; - Promise p; + Promise p; auto tid = std::this_thread::get_id(); bool done = false; std::thread t1([&] { p.getFuture() .via(&x) - .then([&](Try&&) { EXPECT_EQ(tid, std::this_thread::get_id()); }) - .then([&](Try&&) { EXPECT_EQ(tid, std::this_thread::get_id()); }) - .then([&](Try&&) { done = true; }); + .then([&](Try&&) { EXPECT_EQ(tid, std::this_thread::get_id()); }) + .then([&](Try&&) { EXPECT_EQ(tid, std::this_thread::get_id()); }) + .then([&](Try&&) { done = true; }); }); std::thread t2([&] { @@ -448,7 +448,7 @@ TEST(Via, viaRaces) { TEST(ViaFunc, liftsVoid) { ManualExecutor x; int count = 0; - Future f = via(&x, [&]{ count++; }); + Future f = via(&x, [&]{ count++; }); EXPECT_EQ(0, count); x.run(); diff --git a/folly/futures/test/WaitTest.cpp b/folly/futures/test/WaitTest.cpp index d2b91f99..b2736f12 100644 --- a/folly/futures/test/WaitTest.cpp +++ b/folly/futures/test/WaitTest.cpp @@ -34,7 +34,7 @@ TEST(Wait, waitImmediate) { EXPECT_EQ(v.size(), done_v.size()); EXPECT_EQ(v, done_v); - vector> v_f; + vector> v_f; v_f.push_back(makeFuture()); v_f.push_back(makeFuture()); auto done_v_f = collectAll(v_f).wait().value(); @@ -169,7 +169,7 @@ TEST(Wait, waitWithDuration) { } { - Promise p; + Promise p; auto start = std::chrono::steady_clock::now(); auto f = p.getFuture().wait(milliseconds(100)); auto elapsed = std::chrono::steady_clock::now() - start; @@ -182,7 +182,7 @@ TEST(Wait, waitWithDuration) { { // Try to trigger the race where the resultant Future is not yet complete // even if we didn't hit the timeout, and make sure we deal with it properly - Promise p; + Promise p; folly::Baton<> b; auto t = std::thread([&]{ b.post(); diff --git a/folly/futures/test/WindowTest.cpp b/folly/futures/test/WindowTest.cpp index 9dbdb156..a7e9b828 100644 --- a/folly/futures/test/WindowTest.cpp +++ b/folly/futures/test/WindowTest.cpp @@ -57,14 +57,14 @@ TEST(Window, basic) { fn(input, 1, 0); } { - // int -> Future + // int -> Future auto res = reduce( window( std::vector({1, 2, 3}), [](int i) { return makeFuture(); }, 2), 0, - [](int sum, const Try& b) { + [](int sum, const Try& b) { EXPECT_TRUE(b.hasValue()); return sum + 1; }).get();