suppress warnings in tests for deprecated functions
[folly.git] / folly / futures / Future-pre.h
1 /*
2  * Copyright 2015-present 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 isFutureOrSemiFuture : std::false_type {
50   using Inner = typename Unit::Lift<T>::type;
51   using Return = Inner;
52 };
53
54 template <typename T>
55 struct isFutureOrSemiFuture<Future<T>> : std::true_type {
56   typedef T Inner;
57   using Return = Future<Inner>;
58 };
59
60 template <typename T>
61 struct isFutureOrSemiFuture<SemiFuture<T>> : std::true_type {
62   typedef T Inner;
63   using Return = SemiFuture<Inner>;
64 };
65
66 template <typename T>
67 struct isTry : std::false_type {};
68
69 template <typename T>
70 struct isTry<Try<T>> : std::true_type {};
71
72 namespace futures {
73 namespace detail {
74
75 template <class> class Core;
76 template <class...> struct CollectAllVariadicContext;
77 template <class...> struct CollectVariadicContext;
78 template <class> struct CollectContext;
79
80 template <typename F, typename... Args>
81 using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
82
83 template <typename...>
84 struct ArgType;
85
86 template <typename Arg, typename... Args>
87 struct ArgType<Arg, Args...> {
88   typedef Arg FirstArg;
89 };
90
91 template <>
92 struct ArgType<> {
93   typedef void FirstArg;
94 };
95
96 template <bool isTry, typename F, typename... Args>
97 struct argResult {
98   using Result = resultOf<F, Args...>;
99 };
100
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{}; }
106
107     template <typename>
108     static constexpr std::false_type
109     check(...) { return std::false_type{}; }
110
111     typedef decltype(check<F>(nullptr)) type;
112     static constexpr bool value = type::value;
113 };
114
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;
132 };
133
134 template <typename L>
135 struct Extract : Extract<decltype(&L::operator())> { };
136
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;
143 };
144
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;
151 };
152
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;
159 };
160
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;
167 };
168
169 /**
170  * Defer work until executor is actively boosted.
171  *
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.
176  */
177 class DeferredExecutor final : public Executor {
178  public:
179   template <typename Class, typename F>
180   struct DeferredWorkWrapper;
181
182   /**
183    * Work wrapper class to capture the keepalive and forward the argument
184    * list to the captured function.
185    */
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)...);
190     }
191
192     Executor::KeepAlive a;
193     F func;
194   };
195
196   /**
197    * Construction is private to ensure that creation and deletion are
198    * symmetric
199    */
200   static KeepAlive create() {
201     std::unique_ptr<futures::detail::DeferredExecutor> devb{
202         new futures::detail::DeferredExecutor{}};
203     auto keepAlive = devb->getKeepAliveToken();
204     devb.release();
205     return keepAlive;
206   }
207
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.
211     if (func_) {
212       func_ = [oldFunc = std::move(func_), func = std::move(func)]() mutable {
213         oldFunc();
214         func();
215       };
216     } else {
217       func_ = std::move(func);
218     }
219   }
220
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
224   void boost() {
225     // Ensure that the DeferredExecutor outlives its run operation
226     ++keepAliveCount_;
227     SCOPE_EXIT {
228       releaseAndTryFree();
229     };
230
231     // Drain the executor
232     while (auto func = std::move(func_)) {
233       func();
234     }
235   }
236
237   KeepAlive getKeepAliveToken() override {
238     keepAliveAcquire();
239     return makeKeepAlive();
240   }
241
242   ~DeferredExecutor() = default;
243
244   template <class F>
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)};
249   }
250
251  protected:
252   void keepAliveAcquire() override {
253     ++keepAliveCount_;
254   }
255
256   void keepAliveRelease() override {
257     releaseAndTryFree();
258   }
259
260   void releaseAndTryFree() {
261     --keepAliveCount_;
262     if (keepAliveCount_ == 0) {
263       delete this;
264     }
265   }
266
267  private:
268   Func func_;
269   ssize_t keepAliveCount_{0};
270
271   DeferredExecutor() = default;
272 };
273
274 } // namespace detail
275 } // namespace futures
276
277 class Timekeeper;
278
279 } // namespace folly