Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / wangle / Later-inl.h
1 /*
2  * Copyright 2014 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 #include <folly/wangle/Executor.h>
20 #include <folly/wangle/Future.h>
21 #include <folly/Optional.h>
22
23 namespace folly { namespace wangle {
24
25 template <typename T>
26 struct isLater {
27   static const bool value = false;
28 };
29
30 template <typename T>
31 struct isLater<Later<T> > {
32   static const bool value = true;
33 };
34
35 template <typename T>
36 struct isLaterOrFuture {
37   static const bool value = false;
38 };
39
40 template <typename T>
41 struct isLaterOrFuture<Later<T>> {
42   static const bool value = true;
43 };
44
45 template <typename T>
46 struct isLaterOrFuture<Future<T>> {
47   static const bool value = true;
48 };
49
50 template <typename T>
51 template <class U, class Unused, class Unused2>
52 Later<T>::Later() {
53   future_ = starter_.getFuture();
54 }
55
56 template <class T>
57 Later<T>::Later(Future<T>&& f) {
58   MoveWrapper<Future<T>> fw(std::move(f));
59   *this = Later<void>()
60     .then([fw](Try<void>&&) mutable {
61       return std::move(*fw);
62     });
63 }
64
65 template <typename T>
66 Later<T>::Later(Promise<void>&& starter)
67   : starter_(std::forward<Promise<void>>(starter)) { }
68
69 template <class T>
70 template <class U, class Unused, class Unused2>
71 Later<T>::Later(U&& input) {
72   folly::MoveWrapper<Promise<U>> promise;
73   folly::MoveWrapper<U> inputm(std::forward<U>(input));
74   future_ = promise->getFuture();
75   starter_.getFuture().then([=](Try<void>&& t) mutable {
76     promise->setValue(std::move(*inputm));
77   });
78 }
79
80 template <class T>
81 template <class U, class Unused, class Unused2>
82 Later<T>::Later(std::function<void(std::function<void(U&&)>&&)>&& fn) {
83   folly::MoveWrapper<Promise<U>> promise;
84   future_ = promise->getFuture();
85   starter_.getFuture().then([=](Try<void>&& t) mutable {
86     fn([=](U&& output) mutable {
87       promise->setValue(std::move(output));
88     });
89   });
90 }
91
92 template <class T>
93 template <class F>
94 typename std::enable_if<
95   !isLaterOrFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
96   Later<typename std::result_of<F(Try<T>&&)>::type> >::type
97 Later<T>::then(F&& fn) {
98   typedef typename std::result_of<F(Try<T>&&)>::type B;
99
100   Later<B> later(std::move(starter_));
101   later.future_ = future_->then(std::forward<F>(fn));
102   return later;
103 }
104
105 template <class T>
106 template <class F>
107 typename std::enable_if<
108   isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
109   Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
110 Later<T>::then(F&& fn) {
111   typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
112
113   Later<B> later(std::move(starter_));
114   later.future_ = future_->then(std::move(fn));
115   return later;
116 }
117
118 template <class T>
119 template <class F>
120 typename std::enable_if<
121   isLater<typename std::result_of<F(Try<T>&&)>::type>::value,
122   Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
123 Later<T>::then(F&& fn) {
124   typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
125
126   folly::MoveWrapper<Promise<B>> promise;
127   folly::MoveWrapper<F> fnm(std::move(fn));
128   Later<B> later(std::move(starter_));
129   later.future_ = promise->getFuture();
130   future_->then([=](Try<T>&& t) mutable {
131     (*fnm)(std::move(t))
132     .then([=](Try<B>&& t2) mutable {
133       promise->fulfilTry(std::move(t2));
134     })
135     .launch();
136   });
137   return later;
138 }
139
140 template <class T>
141 Later<T> Later<T>::via(Executor* executor) {
142   folly::MoveWrapper<Promise<T>> promise;
143   Later<T> later(std::move(starter_));
144   later.future_ = promise->getFuture();
145
146   future_->setCallback_([executor, promise](Try<T>&& t) mutable {
147     folly::MoveWrapper<Try<T>> tt(std::move(t));
148     executor->add([promise, tt]() mutable {
149       promise->fulfilTry(std::move(*tt));
150     });
151   });
152
153   return later;
154 }
155
156 template <class T>
157 Future<T> Later<T>::launch() {
158   starter_.setValue();
159   return std::move(*future_);
160 }
161
162 }}