Quick comment on DE to clarify use cases and lack of thread safety.
[folly.git] / folly / futures / Future-pre.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #pragma once
18
19 // included by Future.h, do not include directly.
20
21 namespace folly {
22
23 template <class> class Promise;
24
25 template <class T>
26 class SemiFuture;
27
28 template <typename T>
29 struct isSemiFuture : std::false_type {
30   using Inner = typename Unit::Lift<T>::type;
31 };
32
33 template <typename T>
34 struct isSemiFuture<SemiFuture<T>> : std::true_type {
35   typedef T Inner;
36 };
37
38 template <typename T>
39 struct isSemiFuture<Future<T>> : std::true_type {
40   typedef T Inner;
41 };
42
43 template <typename T>
44 struct isFuture : std::false_type {
45   using Inner = typename Unit::Lift<T>::type;
46 };
47
48 template <typename T>
49 struct isFuture<Future<T>> : std::true_type {
50   typedef T Inner;
51 };
52
53 template <typename T>
54 struct isTry : std::false_type {};
55
56 template <typename T>
57 struct isTry<Try<T>> : std::true_type {};
58
59 namespace futures {
60 namespace detail {
61
62 template <class> class Core;
63 template <class...> struct CollectAllVariadicContext;
64 template <class...> struct CollectVariadicContext;
65 template <class> struct CollectContext;
66
67 template <typename F, typename... Args>
68 using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
69
70 template <typename...>
71 struct ArgType;
72
73 template <typename Arg, typename... Args>
74 struct ArgType<Arg, Args...> {
75   typedef Arg FirstArg;
76 };
77
78 template <>
79 struct ArgType<> {
80   typedef void FirstArg;
81 };
82
83 template <bool isTry, typename F, typename... Args>
84 struct argResult {
85   using Result = resultOf<F, Args...>;
86 };
87
88 template <typename F, typename... Args>
89 struct callableWith {
90     template <typename T, typename = detail::resultOf<T, Args...>>
91     static constexpr std::true_type
92     check(std::nullptr_t) { return std::true_type{}; }
93
94     template <typename>
95     static constexpr std::false_type
96     check(...) { return std::false_type{}; }
97
98     typedef decltype(check<F>(nullptr)) type;
99     static constexpr bool value = type::value;
100 };
101
102 template <typename T, typename F>
103 struct callableResult {
104   typedef typename std::conditional<
105     callableWith<F>::value,
106     detail::argResult<false, F>,
107     typename std::conditional<
108       callableWith<F, T&&>::value,
109       detail::argResult<false, F, T&&>,
110       typename std::conditional<
111         callableWith<F, T&>::value,
112         detail::argResult<false, F, T&>,
113         typename std::conditional<
114           callableWith<F, Try<T>&&>::value,
115           detail::argResult<true, F, Try<T>&&>,
116           detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
117   typedef isFuture<typename Arg::Result> ReturnsFuture;
118   typedef Future<typename ReturnsFuture::Inner> Return;
119 };
120
121 template <typename L>
122 struct Extract : Extract<decltype(&L::operator())> { };
123
124 template <typename Class, typename R, typename... Args>
125 struct Extract<R(Class::*)(Args...) const> {
126   typedef isFuture<R> ReturnsFuture;
127   typedef Future<typename ReturnsFuture::Inner> Return;
128   typedef typename ReturnsFuture::Inner RawReturn;
129   typedef typename ArgType<Args...>::FirstArg FirstArg;
130 };
131
132 template <typename Class, typename R, typename... Args>
133 struct Extract<R(Class::*)(Args...)> {
134   typedef isFuture<R> ReturnsFuture;
135   typedef Future<typename ReturnsFuture::Inner> Return;
136   typedef typename ReturnsFuture::Inner RawReturn;
137   typedef typename ArgType<Args...>::FirstArg FirstArg;
138 };
139
140 template <typename R, typename... Args>
141 struct Extract<R (*)(Args...)> {
142   typedef isFuture<R> ReturnsFuture;
143   typedef Future<typename ReturnsFuture::Inner> Return;
144   typedef typename ReturnsFuture::Inner RawReturn;
145   typedef typename ArgType<Args...>::FirstArg FirstArg;
146 };
147
148 template <typename R, typename... Args>
149 struct Extract<R (&)(Args...)> {
150   typedef isFuture<R> ReturnsFuture;
151   typedef Future<typename ReturnsFuture::Inner> Return;
152   typedef typename ReturnsFuture::Inner RawReturn;
153   typedef typename ArgType<Args...>::FirstArg FirstArg;
154 };
155
156 /**
157  * Defer work until executor is actively boosted.
158  *
159  * NOTE: that this executor is a private implementation detail belonging to the
160  * Folly Futures library and not intended to be used elsewhere. It is designed
161  * specifically for the use case of deferring work on a SemiFuture. It is NOT
162  * thread safe. Please do not use for any other purpose without great care.
163  */
164 class DeferredExecutor final : public Executor {
165  public:
166   template <typename Class, typename F>
167   struct DeferredWorkWrapper;
168
169   /**
170    * Work wrapper class to capture the keepalive and forward the argument
171    * list to the captured function.
172    */
173   template <typename F, typename R, typename... Args>
174   struct DeferredWorkWrapper<F, R (F::*)(Args...) const> {
175     R operator()(Args... args) {
176       return func(std::forward<Args>(args)...);
177     }
178
179     Executor::KeepAlive a;
180     F func;
181   };
182
183   /**
184    * Construction is private to ensure that creation and deletion are
185    * symmetric
186    */
187   static KeepAlive create() {
188     std::unique_ptr<futures::detail::DeferredExecutor> devb{
189         new futures::detail::DeferredExecutor{}};
190     auto keepAlive = devb->getKeepAliveToken();
191     devb.release();
192     return keepAlive;
193   }
194
195   /// Enqueue a function to executed by this executor. This is not thread-safe.
196   void add(Func func) override {
197     // If we already have a function, wrap and chain. Otherwise assign.
198     if (func_) {
199       func_ = [oldFunc = std::move(func_), func = std::move(func)]() mutable {
200         oldFunc();
201         func();
202       };
203     } else {
204       func_ = std::move(func);
205     }
206   }
207
208   // Boost is like drive for certain types of deferred work
209   // Unlike drive it is safe to run on another executor because it
210   // will only be implemented on deferred-safe executors
211   void boost() {
212     // Ensure that the DeferredExecutor outlives its run operation
213     ++keepAliveCount_;
214     SCOPE_EXIT {
215       releaseAndTryFree();
216     };
217
218     // Drain the executor
219     while (auto func = std::move(func_)) {
220       func();
221     }
222   }
223
224   KeepAlive getKeepAliveToken() override {
225     keepAliveAcquire();
226     return makeKeepAlive();
227   }
228
229   ~DeferredExecutor() = default;
230
231   template <class F>
232   static auto wrap(Executor::KeepAlive keepAlive, F&& func)
233       -> DeferredWorkWrapper<F, decltype(&F::operator())> {
234     return DeferredExecutor::DeferredWorkWrapper<F, decltype(&F::operator())>{
235         std::move(keepAlive), std::forward<F>(func)};
236   }
237
238  protected:
239   void keepAliveAcquire() override {
240     ++keepAliveCount_;
241   }
242
243   void keepAliveRelease() override {
244     releaseAndTryFree();
245   }
246
247   void releaseAndTryFree() {
248     --keepAliveCount_;
249     if (keepAliveCount_ == 0) {
250       delete this;
251     }
252   }
253
254  private:
255   Func func_;
256   ssize_t keepAliveCount_{0};
257
258   DeferredExecutor() = default;
259 };
260
261 } // namespace detail
262 } // namespace futures
263
264 class Timekeeper;
265
266 } // namespace folly