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 isFutureOrSemiFuture : std::false_type {
50 using Inner = typename Unit::Lift<T>::type;
55 struct isFutureOrSemiFuture<Future<T>> : std::true_type {
57 using Return = Future<Inner>;
61 struct isFutureOrSemiFuture<SemiFuture<T>> : std::true_type {
63 using Return = SemiFuture<Inner>;
67 struct isTry : std::false_type {};
70 struct isTry<Try<T>> : std::true_type {};
75 template <class> class Core;
76 template <class...> struct CollectAllVariadicContext;
77 template <class...> struct CollectVariadicContext;
78 template <class> struct CollectContext;
80 template <typename F, typename... Args>
81 using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
83 template <typename...>
86 template <typename Arg, typename... Args>
87 struct ArgType<Arg, Args...> {
93 typedef void FirstArg;
96 template <bool isTry, typename F, typename... Args>
98 using Result = resultOf<F, Args...>;
101 template <typename F, typename... Args>
102 struct callableWith {
103 template <typename T, typename = detail::resultOf<T, Args...>>
104 static constexpr std::true_type
105 check(std::nullptr_t) { return std::true_type{}; }
108 static constexpr std::false_type
109 check(...) { return std::false_type{}; }
111 typedef decltype(check<F>(nullptr)) type;
112 static constexpr bool value = type::value;
115 template <typename T, typename F>
116 struct callableResult {
117 typedef typename std::conditional<
118 callableWith<F>::value,
119 detail::argResult<false, F>,
120 typename std::conditional<
121 callableWith<F, T&&>::value,
122 detail::argResult<false, F, T&&>,
123 typename std::conditional<
124 callableWith<F, T&>::value,
125 detail::argResult<false, F, T&>,
126 typename std::conditional<
127 callableWith<F, Try<T>&&>::value,
128 detail::argResult<true, F, Try<T>&&>,
129 detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
130 typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture;
131 typedef Future<typename ReturnsFuture::Inner> Return;
134 template <typename L>
135 struct Extract : Extract<decltype(&L::operator())> { };
137 template <typename Class, typename R, typename... Args>
138 struct Extract<R(Class::*)(Args...) const> {
139 typedef isFutureOrSemiFuture<R> ReturnsFuture;
140 typedef Future<typename ReturnsFuture::Inner> Return;
141 typedef typename ReturnsFuture::Inner RawReturn;
142 typedef typename ArgType<Args...>::FirstArg FirstArg;
145 template <typename Class, typename R, typename... Args>
146 struct Extract<R(Class::*)(Args...)> {
147 typedef isFutureOrSemiFuture<R> ReturnsFuture;
148 typedef Future<typename ReturnsFuture::Inner> Return;
149 typedef typename ReturnsFuture::Inner RawReturn;
150 typedef typename ArgType<Args...>::FirstArg FirstArg;
153 template <typename R, typename... Args>
154 struct Extract<R (*)(Args...)> {
155 typedef isFutureOrSemiFuture<R> ReturnsFuture;
156 typedef Future<typename ReturnsFuture::Inner> Return;
157 typedef typename ReturnsFuture::Inner RawReturn;
158 typedef typename ArgType<Args...>::FirstArg FirstArg;
161 template <typename R, typename... Args>
162 struct Extract<R (&)(Args...)> {
163 typedef isFutureOrSemiFuture<R> ReturnsFuture;
164 typedef Future<typename ReturnsFuture::Inner> Return;
165 typedef typename ReturnsFuture::Inner RawReturn;
166 typedef typename ArgType<Args...>::FirstArg FirstArg;
170 * Defer work until executor is actively boosted.
172 * NOTE: that this executor is a private implementation detail belonging to the
173 * Folly Futures library and not intended to be used elsewhere. It is designed
174 * specifically for the use case of deferring work on a SemiFuture. It is NOT
175 * thread safe. Please do not use for any other purpose without great care.
177 class DeferredExecutor final : public Executor {
179 template <typename Class, typename F>
180 struct DeferredWorkWrapper;
183 * Work wrapper class to capture the keepalive and forward the argument
184 * list to the captured function.
186 template <typename F, typename R, typename... Args>
187 struct DeferredWorkWrapper<F, R (F::*)(Args...) const> {
188 R operator()(Args... args) {
189 return func(std::forward<Args>(args)...);
192 Executor::KeepAlive a;
197 * Construction is private to ensure that creation and deletion are
200 static KeepAlive create() {
201 std::unique_ptr<futures::detail::DeferredExecutor> devb{
202 new futures::detail::DeferredExecutor{}};
203 auto keepAlive = devb->getKeepAliveToken();
208 /// Enqueue a function to executed by this executor. This is not thread-safe.
209 void add(Func func) override {
210 // If we already have a function, wrap and chain. Otherwise assign.
212 func_ = [oldFunc = std::move(func_), func = std::move(func)]() mutable {
217 func_ = std::move(func);
221 // Boost is like drive for certain types of deferred work
222 // Unlike drive it is safe to run on another executor because it
223 // will only be implemented on deferred-safe executors
225 // Ensure that the DeferredExecutor outlives its run operation
231 // Drain the executor
232 while (auto func = std::move(func_)) {
237 KeepAlive getKeepAliveToken() override {
239 return makeKeepAlive();
242 ~DeferredExecutor() = default;
245 static auto wrap(Executor::KeepAlive keepAlive, F&& func)
246 -> DeferredWorkWrapper<F, decltype(&F::operator())> {
247 return DeferredExecutor::DeferredWorkWrapper<F, decltype(&F::operator())>{
248 std::move(keepAlive), std::forward<F>(func)};
252 void keepAliveAcquire() override {
256 void keepAliveRelease() override {
260 void releaseAndTryFree() {
262 if (keepAliveCount_ == 0) {
269 ssize_t keepAliveCount_{0};
271 DeferredExecutor() = default;
274 } // namespace detail
275 } // namespace futures