Missing Future/SemiFuture->Value conversion check
[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 isFuture : std::false_type {
40   using Inner = typename Unit::Lift<T>::type;
41 };
42
43 template <typename T>
44 struct isFuture<Future<T>> : std::true_type {
45   typedef T Inner;
46 };
47
48 template <typename T>
49 struct isTry : std::false_type {};
50
51 template <typename T>
52 struct isTry<Try<T>> : std::true_type {};
53
54 namespace futures {
55 namespace detail {
56
57 template <class> class Core;
58 template <class...> struct CollectAllVariadicContext;
59 template <class...> struct CollectVariadicContext;
60 template <class> struct CollectContext;
61
62 template <typename F, typename... Args>
63 using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
64
65 template <typename...>
66 struct ArgType;
67
68 template <typename Arg, typename... Args>
69 struct ArgType<Arg, Args...> {
70   typedef Arg FirstArg;
71 };
72
73 template <>
74 struct ArgType<> {
75   typedef void FirstArg;
76 };
77
78 template <bool isTry, typename F, typename... Args>
79 struct argResult {
80   using Result = resultOf<F, Args...>;
81 };
82
83 template <typename F, typename... Args>
84 struct callableWith {
85     template <typename T, typename = detail::resultOf<T, Args...>>
86     static constexpr std::true_type
87     check(std::nullptr_t) { return std::true_type{}; }
88
89     template <typename>
90     static constexpr std::false_type
91     check(...) { return std::false_type{}; }
92
93     typedef decltype(check<F>(nullptr)) type;
94     static constexpr bool value = type::value;
95 };
96
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;
114 };
115
116 template <typename L>
117 struct Extract : Extract<decltype(&L::operator())> { };
118
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;
125 };
126
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;
133 };
134
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;
141 };
142
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;
149 };
150
151 /**
152  * Defer work until executor is actively boosted.
153  *
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.
158  */
159 class DeferredExecutor final : public Executor {
160  public:
161   template <typename Class, typename F>
162   struct DeferredWorkWrapper;
163
164   /**
165    * Work wrapper class to capture the keepalive and forward the argument
166    * list to the captured function.
167    */
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)...);
172     }
173
174     Executor::KeepAlive a;
175     F func;
176   };
177
178   /**
179    * Construction is private to ensure that creation and deletion are
180    * symmetric
181    */
182   static KeepAlive create() {
183     std::unique_ptr<futures::detail::DeferredExecutor> devb{
184         new futures::detail::DeferredExecutor{}};
185     auto keepAlive = devb->getKeepAliveToken();
186     devb.release();
187     return keepAlive;
188   }
189
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.
193     if (func_) {
194       func_ = [oldFunc = std::move(func_), func = std::move(func)]() mutable {
195         oldFunc();
196         func();
197       };
198     } else {
199       func_ = std::move(func);
200     }
201   }
202
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
206   void boost() {
207     // Ensure that the DeferredExecutor outlives its run operation
208     ++keepAliveCount_;
209     SCOPE_EXIT {
210       releaseAndTryFree();
211     };
212
213     // Drain the executor
214     while (auto func = std::move(func_)) {
215       func();
216     }
217   }
218
219   KeepAlive getKeepAliveToken() override {
220     keepAliveAcquire();
221     return makeKeepAlive();
222   }
223
224   ~DeferredExecutor() = default;
225
226   template <class F>
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)};
231   }
232
233  protected:
234   void keepAliveAcquire() override {
235     ++keepAliveCount_;
236   }
237
238   void keepAliveRelease() override {
239     releaseAndTryFree();
240   }
241
242   void releaseAndTryFree() {
243     --keepAliveCount_;
244     if (keepAliveCount_ == 0) {
245       delete this;
246     }
247   }
248
249  private:
250   Func func_;
251   ssize_t keepAliveCount_{0};
252
253   DeferredExecutor() = default;
254 };
255
256 } // namespace detail
257 } // namespace futures
258
259 class Timekeeper;
260
261 } // namespace folly