2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 // included by Future.h, do not include directly.
23 template <class> class Promise;
29 struct isSemiFuture : std::false_type {
30 using Inner = typename Unit::Lift<T>::type;
34 struct isSemiFuture<SemiFuture<T>> : std::true_type {
39 struct isFuture : std::false_type {
40 using Inner = typename Unit::Lift<T>::type;
44 struct isFuture<Future<T>> : std::true_type {
49 struct isTry : std::false_type {};
52 struct isTry<Try<T>> : std::true_type {};
57 template <class> class Core;
58 template <class...> struct CollectAllVariadicContext;
59 template <class...> struct CollectVariadicContext;
60 template <class> struct CollectContext;
62 template <typename F, typename... Args>
63 using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
65 template <typename...>
68 template <typename Arg, typename... Args>
69 struct ArgType<Arg, Args...> {
75 typedef void FirstArg;
78 template <bool isTry, typename F, typename... Args>
80 using Result = resultOf<F, Args...>;
83 template <typename F, typename... Args>
85 template <typename T, typename = detail::resultOf<T, Args...>>
86 static constexpr std::true_type
87 check(std::nullptr_t) { return std::true_type{}; }
90 static constexpr std::false_type
91 check(...) { return std::false_type{}; }
93 typedef decltype(check<F>(nullptr)) type;
94 static constexpr bool value = type::value;
97 template <typename T, typename F>
98 struct callableResult {
99 typedef typename std::conditional<
100 callableWith<F>::value,
101 detail::argResult<false, F>,
102 typename std::conditional<
103 callableWith<F, T&&>::value,
104 detail::argResult<false, F, T&&>,
105 typename std::conditional<
106 callableWith<F, T&>::value,
107 detail::argResult<false, F, T&>,
108 typename std::conditional<
109 callableWith<F, Try<T>&&>::value,
110 detail::argResult<true, F, Try<T>&&>,
111 detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
112 typedef isFuture<typename Arg::Result> ReturnsFuture;
113 typedef Future<typename ReturnsFuture::Inner> Return;
116 template <typename L>
117 struct Extract : Extract<decltype(&L::operator())> { };
119 template <typename Class, typename R, typename... Args>
120 struct Extract<R(Class::*)(Args...) const> {
121 typedef isFuture<R> ReturnsFuture;
122 typedef Future<typename ReturnsFuture::Inner> Return;
123 typedef typename ReturnsFuture::Inner RawReturn;
124 typedef typename ArgType<Args...>::FirstArg FirstArg;
127 template <typename Class, typename R, typename... Args>
128 struct Extract<R(Class::*)(Args...)> {
129 typedef isFuture<R> ReturnsFuture;
130 typedef Future<typename ReturnsFuture::Inner> Return;
131 typedef typename ReturnsFuture::Inner RawReturn;
132 typedef typename ArgType<Args...>::FirstArg FirstArg;
135 template <typename R, typename... Args>
136 struct Extract<R (*)(Args...)> {
137 typedef isFuture<R> ReturnsFuture;
138 typedef Future<typename ReturnsFuture::Inner> Return;
139 typedef typename ReturnsFuture::Inner RawReturn;
140 typedef typename ArgType<Args...>::FirstArg FirstArg;
143 template <typename R, typename... Args>
144 struct Extract<R (&)(Args...)> {
145 typedef isFuture<R> ReturnsFuture;
146 typedef Future<typename ReturnsFuture::Inner> Return;
147 typedef typename ReturnsFuture::Inner RawReturn;
148 typedef typename ArgType<Args...>::FirstArg FirstArg;
152 * Defer work until executor is actively boosted.
154 * NOTE: that this executor is a private implementation detail belonging to the
155 * Folly Futures library and not intended to be used elsewhere. It is designed
156 * specifically for the use case of deferring work on a SemiFuture. It is NOT
157 * thread safe. Please do not use for any other purpose without great care.
159 class DeferredExecutor final : public Executor {
161 template <typename Class, typename F>
162 struct DeferredWorkWrapper;
165 * Work wrapper class to capture the keepalive and forward the argument
166 * list to the captured function.
168 template <typename F, typename R, typename... Args>
169 struct DeferredWorkWrapper<F, R (F::*)(Args...) const> {
170 R operator()(Args... args) {
171 return func(std::forward<Args>(args)...);
174 Executor::KeepAlive a;
179 * Construction is private to ensure that creation and deletion are
182 static KeepAlive create() {
183 std::unique_ptr<futures::detail::DeferredExecutor> devb{
184 new futures::detail::DeferredExecutor{}};
185 auto keepAlive = devb->getKeepAliveToken();
190 /// Enqueue a function to executed by this executor. This is not thread-safe.
191 void add(Func func) override {
192 // If we already have a function, wrap and chain. Otherwise assign.
194 func_ = [oldFunc = std::move(func_), func = std::move(func)]() mutable {
199 func_ = std::move(func);
203 // Boost is like drive for certain types of deferred work
204 // Unlike drive it is safe to run on another executor because it
205 // will only be implemented on deferred-safe executors
207 // Ensure that the DeferredExecutor outlives its run operation
213 // Drain the executor
214 while (auto func = std::move(func_)) {
219 KeepAlive getKeepAliveToken() override {
221 return makeKeepAlive();
224 ~DeferredExecutor() = default;
227 static auto wrap(Executor::KeepAlive keepAlive, F&& func)
228 -> DeferredWorkWrapper<F, decltype(&F::operator())> {
229 return DeferredExecutor::DeferredWorkWrapper<F, decltype(&F::operator())>{
230 std::move(keepAlive), std::forward<F>(func)};
234 void keepAliveAcquire() override {
238 void keepAliveRelease() override {
242 void releaseAndTryFree() {
244 if (keepAliveCount_ == 0) {
251 ssize_t keepAliveCount_{0};
253 DeferredExecutor() = default;
256 } // namespace detail
257 } // namespace futures