return std::move(f).via(executor, priority);
}
+
+template <class Func>
+auto via(Executor* x, Func func)
+ -> Future<typename isFuture<decltype(func())>::Inner>
+// this would work, if not for Future<void> :-/
+// -> decltype(via(x).then(func))
+{
+ // TODO make this actually more performant. :-P #7260175
+ return via(x).then(func);
+}
+
template <class T>
bool Future<T>::isReady() const {
throwIfInvalid();
return map(c.begin(), c.end(), std::forward<F>(func));
}
-}
+} // namespace futures
/**
Make a completed Future by moving in a value. e.g.
Executor* executor,
int8_t priority = Executor::MID_PRI);
+/// Execute a function via the given executor and return a future.
+/// This is semantically equivalent to via(executor).then(func), but
+/// easier to read and slightly more efficient.
+template <class Func>
+auto via(Executor*, Func func)
+ -> Future<typename isFuture<decltype(func())>::Inner>;
+
/** When all the input Futures complete, the returned Future will complete.
Errors do not cause early termination; this Future will always succeed
after all its Futures have finished (whether successfully or with an
std::forward<F>(func));
}
-} // namespace folly
+} // namespace
t2.join();
}
-TEST(Future, callbackRace) {
+TEST(Via, callbackRace) {
ThreadExecutor x;
auto fn = [&x]{
fn().wait();
}
+
+TEST(ViaFunc, liftsVoid) {
+ ManualExecutor x;
+ int count = 0;
+ Future<void> f = via(&x, [&]{ count++; });
+
+ EXPECT_EQ(0, count);
+ x.run();
+ EXPECT_EQ(1, count);
+}
+
+TEST(ViaFunc, value) {
+ ManualExecutor x;
+ EXPECT_EQ(42, via(&x, []{ return 42; }).getVia(&x));
+}
+
+TEST(ViaFunc, exception) {
+ ManualExecutor x;
+ EXPECT_THROW(
+ via(&x, []() -> int { throw std::runtime_error("expected"); })
+ .getVia(&x),
+ std::runtime_error);
+}
+
+TEST(ViaFunc, future) {
+ ManualExecutor x;
+ EXPECT_EQ(42, via(&x, []{ return makeFuture(42); })
+ .getVia(&x));
+}
+
+TEST(ViaFunc, voidFuture) {
+ ManualExecutor x;
+ int count = 0;
+ via(&x, [&]{ count++; }).getVia(&x);
+ EXPECT_EQ(1, count);
+}
+
+TEST(ViaFunc, isSticky) {
+ ManualExecutor x;
+ int count = 0;
+
+ auto f = via(&x, [&]{ count++; });
+ x.run();
+
+ f.then([&]{ count++; });
+ EXPECT_EQ(1, count);
+ x.run();
+ EXPECT_EQ(2, count);
+}