Harden failure signal handler in the face of memory corruptions
[folly.git] / folly / gen / Core-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 #ifndef FOLLY_GEN_CORE_H
18 #error This file may only be included from folly/gen/Core.h
19 #endif
20
21 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic ignored "-Wshadow"
24
25 namespace folly { namespace gen {
26
27 /**
28  * IsCompatibleSignature - Trait type for testing whether a given Functor
29  * matches an expected signature.
30  *
31  * Usage:
32  *   IsCompatibleSignature<FunctorType, bool(int, float)>::value
33  */
34 template<class Candidate, class Expected>
35 class IsCompatibleSignature {
36   static constexpr bool value = false;
37 };
38
39 template<class Candidate,
40          class ExpectedReturn,
41          class... ArgTypes>
42 class IsCompatibleSignature<Candidate, ExpectedReturn(ArgTypes...)> {
43   template<class F,
44            class ActualReturn =
45              decltype(std::declval<F>()(std::declval<ArgTypes>()...)),
46            bool good = std::is_same<ExpectedReturn, ActualReturn>::value>
47   static constexpr bool testArgs(int* p) {
48     return good;
49   }
50
51   template<class F>
52   static constexpr bool testArgs(...) {
53     return false;
54   }
55 public:
56   static constexpr bool value = testArgs<Candidate>(nullptr);
57 };
58
59 /**
60  * FBounded - Helper type for the curiously recurring template pattern, used
61  * heavily here to enable inlining and obviate virtual functions
62  */
63 template<class Self>
64 struct FBounded {
65   const Self& self() const {
66     return *static_cast<const Self*>(this);
67   }
68
69   Self& self() {
70     return *static_cast<Self*>(this);
71   }
72 };
73
74 /**
75  * Operator - Core abstraction of an operation which may be applied to a
76  * generator. All operators implement a method compose(), which takes a
77  * generator and produces an output generator.
78  */
79 template<class Self>
80 class Operator : public FBounded<Self> {
81  public:
82   /**
83    * compose() - Must be implemented by child class to compose a new Generator
84    * out of a given generator. This function left intentionally unimplemented.
85    */
86   template<class Source,
87            class Value,
88            class ResultGen = void>
89   ResultGen compose(const GenImpl<Value, Source>& source) const;
90
91  protected:
92   Operator() = default;
93   Operator(const Operator&) = default;
94   Operator(Operator&&) = default;
95 };
96
97 /**
98  * operator|() - For composing two operators without binding it to a
99  * particular generator.
100  */
101 template<class Left,
102          class Right,
103          class Composed = detail::Composed<Left, Right>>
104 Composed operator|(const Operator<Left>& left,
105                    const Operator<Right>& right) {
106   return Composed(left.self(), right.self());
107 }
108
109 template<class Left,
110          class Right,
111          class Composed = detail::Composed<Left, Right>>
112 Composed operator|(const Operator<Left>& left,
113                    Operator<Right>&& right) {
114   return Composed(left.self(), std::move(right.self()));
115 }
116
117 template<class Left,
118          class Right,
119          class Composed = detail::Composed<Left, Right>>
120 Composed operator|(Operator<Left>&& left,
121                    const Operator<Right>& right) {
122   return Composed(std::move(left.self()), right.self());
123 }
124
125 template<class Left,
126          class Right,
127          class Composed = detail::Composed<Left, Right>>
128 Composed operator|(Operator<Left>&& left,
129                    Operator<Right>&& right) {
130   return Composed(std::move(left.self()), std::move(right.self()));
131 }
132
133 /**
134  * GenImpl - Core abstraction of a generator, an object which produces values by
135  * passing them to a given handler lambda. All generator implementations must
136  * implement apply(). foreach() may also be implemented to special case the
137  * condition where the entire sequence is consumed.
138  */
139 template<class Value,
140          class Self>
141 class GenImpl : public FBounded<Self> {
142  protected:
143   // To prevent slicing
144   GenImpl() = default;
145   GenImpl(const GenImpl&) = default;
146   GenImpl(GenImpl&&) = default;
147
148  public:
149   typedef Value ValueType;
150   typedef typename std::decay<Value>::type StorageType;
151
152   /**
153    * apply() - Send all values produced by this generator to given handler until
154    * the handler returns false. Returns false if and only if the handler passed
155    * in returns false. Note: It should return true even if it completes (without
156    * the handler returning false), as 'Chain' uses the return value of apply to
157    * determine if it should process the second object in its chain.
158    */
159   template<class Handler>
160   bool apply(Handler&& handler) const;
161
162   /**
163    * foreach() - Send all values produced by this generator to given lambda.
164    */
165   template<class Body>
166   void foreach(Body&& body) const {
167     this->self().apply([&](Value value) -> bool {
168         static_assert(!infinite, "Cannot call foreach on infinite GenImpl");
169         body(std::forward<Value>(value));
170         return true;
171       });
172   }
173
174   // Child classes should override if the sequence generated is *definitely*
175   // infinite. 'infinite' may be false_type for some infinite sequences
176   // (due the the Halting Problem).
177   static constexpr bool infinite = false;
178 };
179
180 template<class LeftValue,
181          class Left,
182          class RightValue,
183          class Right,
184          class Chain = detail::Chain<LeftValue, Left, Right>>
185 Chain operator+(const GenImpl<LeftValue, Left>& left,
186                 const GenImpl<RightValue, Right>& right) {
187   static_assert(
188     std::is_same<LeftValue, RightValue>::value,
189     "Generators may ony be combined if Values are the exact same type.");
190   return Chain(left.self(), right.self());
191 }
192
193 template<class LeftValue,
194          class Left,
195          class RightValue,
196          class Right,
197          class Chain = detail::Chain<LeftValue, Left, Right>>
198 Chain operator+(const GenImpl<LeftValue, Left>& left,
199                 GenImpl<RightValue, Right>&& right) {
200   static_assert(
201     std::is_same<LeftValue, RightValue>::value,
202     "Generators may ony be combined if Values are the exact same type.");
203   return Chain(left.self(), std::move(right.self()));
204 }
205
206 template<class LeftValue,
207          class Left,
208          class RightValue,
209          class Right,
210          class Chain = detail::Chain<LeftValue, Left, Right>>
211 Chain operator+(GenImpl<LeftValue, Left>&& left,
212                 const GenImpl<RightValue, Right>& right) {
213   static_assert(
214     std::is_same<LeftValue, RightValue>::value,
215     "Generators may ony be combined if Values are the exact same type.");
216   return Chain(std::move(left.self()), right.self());
217 }
218
219 template<class LeftValue,
220          class Left,
221          class RightValue,
222          class Right,
223          class Chain = detail::Chain<LeftValue, Left, Right>>
224 Chain operator+(GenImpl<LeftValue, Left>&& left,
225                 GenImpl<RightValue, Right>&& right) {
226   static_assert(
227     std::is_same<LeftValue, RightValue>::value,
228     "Generators may ony be combined if Values are the exact same type.");
229   return Chain(std::move(left.self()), std::move(right.self()));
230 }
231
232 /**
233  * operator|() which enables foreach-like usage:
234  *   gen | [](Value v) -> void {...};
235  */
236 template<class Value,
237          class Gen,
238          class Handler>
239 typename std::enable_if<
240   IsCompatibleSignature<Handler, void(Value)>::value>::type
241 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
242   static_assert(!Gen::infinite,
243                 "Cannot pull all values from an infinite sequence.");
244   gen.self().foreach(std::forward<Handler>(handler));
245 }
246
247 /**
248  * operator|() which enables foreach-like usage with 'break' support:
249  *   gen | [](Value v) -> bool { return shouldContinue(); };
250  */
251 template<class Value,
252          class Gen,
253          class Handler>
254 typename std::enable_if<
255   IsCompatibleSignature<Handler, bool(Value)>::value, bool>::type
256 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
257   return gen.self().apply(std::forward<Handler>(handler));
258 }
259
260 /**
261  * operator|() for composing generators with operators, similar to boosts' range
262  * adaptors:
263  *   gen | map(square) | sum
264  */
265 template<class Value,
266          class Gen,
267          class Op>
268 auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op) ->
269 decltype(op.self().compose(gen.self())) {
270   return op.self().compose(gen.self());
271 }
272
273 template<class Value,
274          class Gen,
275          class Op>
276 auto operator|(GenImpl<Value, Gen>&& gen, const Operator<Op>& op) ->
277 decltype(op.self().compose(std::move(gen.self()))) {
278   return op.self().compose(std::move(gen.self()));
279 }
280
281 namespace detail {
282
283 /**
284  * Composed - For building up a pipeline of operations to perform, absent any
285  * particular source generator. Useful for building up custom pipelines.
286  *
287  * This type is usually used by just piping two operators together:
288  *
289  * auto valuesOf = filter([](Optional<int>& o) { return o.hasValue(); })
290  *               | map([](Optional<int>& o) -> int& { return o.value(); });
291  *
292  *  auto valuesIncluded = from(optionals) | valuesOf | as<vector>();
293  */
294 template<class First,
295          class Second>
296 class Composed : public Operator<Composed<First, Second>> {
297   First first_;
298   Second second_;
299  public:
300   Composed() {}
301
302   Composed(First first, Second second)
303     : first_(std::move(first))
304     , second_(std::move(second)) {}
305
306   template<class Source,
307            class Value,
308            class FirstRet = decltype(std::declval<First>()
309                                      .compose(std::declval<Source>())),
310            class SecondRet = decltype(std::declval<Second>()
311                                       .compose(std::declval<FirstRet>()))>
312   SecondRet compose(const GenImpl<Value, Source>& source) const {
313     return second_.compose(first_.compose(source.self()));
314   }
315
316   template<class Source,
317            class Value,
318            class FirstRet = decltype(std::declval<First>()
319                                      .compose(std::declval<Source>())),
320            class SecondRet = decltype(std::declval<Second>()
321                                       .compose(std::declval<FirstRet>()))>
322   SecondRet compose(GenImpl<Value, Source>&& source) const {
323     return second_.compose(first_.compose(std::move(source.self())));
324   }
325 };
326
327 /**
328  * Chain - For concatenating the values produced by two Generators.
329  *
330  * This type is primarily used through using '+' to combine generators, like:
331  *
332  *   auto nums = seq(1, 10) + seq(20, 30);
333  *   int total = nums | sum;
334  */
335 template<class Value, class First, class Second>
336 class Chain : public GenImpl<Value,
337                              Chain<Value, First, Second>> {
338   First first_;
339   Second second_;
340 public:
341   explicit Chain(First first, Second second)
342       : first_(std::move(first))
343       , second_(std::move(second)) {}
344
345   template<class Handler>
346   bool apply(Handler&& handler) const {
347     return first_.apply(std::forward<Handler>(handler))
348         && second_.apply(std::forward<Handler>(handler));
349   }
350
351   template<class Body>
352   void foreach(Body&& body) const {
353     first_.foreach(std::forward<Body>(body));
354     second_.foreach(std::forward<Body>(body));
355   }
356
357   static constexpr bool infinite = First::infinite || Second::infinite;
358 };
359
360 } // detail
361
362 }} // folly::gen
363
364 #pragma GCC diagnostic pop