Add SemiFuture class.
[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 } // namespace detail
157 } // namespace futures
158
159 class Timekeeper;
160
161 } // namespace