-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
FutureExecutor.h
81 lines (74 loc) · 2.52 KB
/
FutureExecutor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/functional/Invoke.h>
#include <folly/futures/Future.h>
namespace folly {
template <typename ExecutorImpl>
class FutureExecutor : public ExecutorImpl {
public:
template <typename... Args>
explicit FutureExecutor(Args&&... args)
: ExecutorImpl(std::forward<Args>(args)...) {}
/*
* Given a function func that returns a Future<T>, adds that function to the
* contained Executor and returns a Future<T> which will be fulfilled with
* func's result once it has been executed.
*
* For example: auto f = futureExecutor.addFuture([](){
* return doAsyncWorkAndReturnAFuture();
* });
*/
template <typename F>
typename std::enable_if<
folly::isFuture<invoke_result_t<F>>::value,
invoke_result_t<F>>::type
addFuture(F func) {
using T = typename invoke_result_t<F>::value_type;
folly::Promise<T> promise;
auto future = promise.getFuture();
ExecutorImpl::add([promise = std::move(promise),
func = std::move(func)]() mutable {
func().then([promise = std::move(promise)](folly::Try<T>&& t) mutable {
promise.setTry(std::move(t));
});
});
return future;
}
/*
* Similar to addFuture above, but takes a func that returns some non-Future
* type T.
*
* For example: auto f = futureExecutor.addFuture([]() {
* return 42;
* });
*/
template <typename F>
typename std::enable_if<
!folly::isFuture<invoke_result_t<F>>::value,
folly::Future<folly::lift_unit_t<invoke_result_t<F>>>>::type
addFuture(F func) {
using T = folly::lift_unit_t<invoke_result_t<F>>;
folly::Promise<T> promise;
auto future = promise.getFuture();
ExecutorImpl::add(
[promise = std::move(promise), func = std::move(func)]() mutable {
promise.setWith(std::move(func));
});
return future;
}
};
} // namespace folly