1 | /* |
2 | * Copyright 2016-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 | * @author Eric Niebler (eniebler@fb.com), Sven Over (over@fb.com) |
18 | * Acknowledgements: Giuseppe Ottaviano (ott@fb.com) |
19 | */ |
20 | |
21 | /** |
22 | * @class Function |
23 | * |
24 | * @brief A polymorphic function wrapper that is not copyable and does not |
25 | * require the wrapped function to be copy constructible. |
26 | * |
27 | * `folly::Function` is a polymorphic function wrapper, similar to |
28 | * `std::function`. The template parameters of the `folly::Function` define |
29 | * the parameter signature of the wrapped callable, but not the specific |
30 | * type of the embedded callable. E.g. a `folly::Function<int(int)>` |
31 | * can wrap callables that return an `int` when passed an `int`. This can be a |
32 | * function pointer or any class object implementing one or both of |
33 | * |
34 | * int operator(int); |
35 | * int operator(int) const; |
36 | * |
37 | * If both are defined, the non-const one takes precedence. |
38 | * |
39 | * Unlike `std::function`, a `folly::Function` can wrap objects that are not |
40 | * copy constructible. As a consequence of this, `folly::Function` itself |
41 | * is not copyable, either. |
42 | * |
43 | * Another difference is that, unlike `std::function`, `folly::Function` treats |
44 | * const-ness of methods correctly. While a `std::function` allows to wrap |
45 | * an object that only implements a non-const `operator()` and invoke |
46 | * a const-reference of the `std::function`, `folly::Function` requires you to |
47 | * declare a function type as const in order to be able to execute it on a |
48 | * const-reference. |
49 | * |
50 | * For example: |
51 | * |
52 | * class Foo { |
53 | * public: |
54 | * void operator()() { |
55 | * // mutates the Foo object |
56 | * } |
57 | * }; |
58 | * |
59 | * class Bar { |
60 | * std::function<void(void)> foo_; // wraps a Foo object |
61 | * public: |
62 | * void mutateFoo() const |
63 | * { |
64 | * foo_(); |
65 | * } |
66 | * }; |
67 | * |
68 | * Even though `mutateFoo` is a const-method, so it can only reference `foo_` |
69 | * as const, it is able to call the non-const `operator()` of the Foo |
70 | * object that is embedded in the foo_ function. |
71 | * |
72 | * `folly::Function` will not allow you to do that. You will have to decide |
73 | * whether you need to invoke your wrapped callable from a const reference |
74 | * (like in the example above), in which case it will only wrap a |
75 | * `operator() const`. If your functor does not implement that, |
76 | * compilation will fail. If you do not require to be able to invoke the |
77 | * wrapped function in a const context, you can wrap any functor that |
78 | * implements either or both of const and non-const `operator()`. |
79 | * |
80 | * The template parameter of `folly::Function`, the `FunctionType`, can be |
81 | * const-qualified. Be aware that the const is part of the function signature. |
82 | * It does not mean that the function type is a const type. |
83 | * |
84 | * using FunctionType = R(Args...); |
85 | * using ConstFunctionType = R(Args...) const; |
86 | * |
87 | * In this example, `FunctionType` and `ConstFunctionType` are different |
88 | * types. `ConstFunctionType` is not the same as `const FunctionType`. |
89 | * As a matter of fact, trying to use the latter should emit a compiler |
90 | * warning or error, because it has no defined meaning. |
91 | * |
92 | * // This will not compile: |
93 | * folly::Function<void(void) const> func = Foo(); |
94 | * // because Foo does not have a member function of the form: |
95 | * // void operator()() const; |
96 | * |
97 | * // This will compile just fine: |
98 | * folly::Function<void(void)> func = Foo(); |
99 | * // and it will wrap the existing member function: |
100 | * // void operator()(); |
101 | * |
102 | * When should a const function type be used? As a matter of fact, you will |
103 | * probably not need to use const function types very often. See the following |
104 | * example: |
105 | * |
106 | * class Bar { |
107 | * folly::Function<void()> func_; |
108 | * folly::Function<void() const> constFunc_; |
109 | * |
110 | * void someMethod() { |
111 | * // Can call func_. |
112 | * func_(); |
113 | * // Can call constFunc_. |
114 | * constFunc_(); |
115 | * } |
116 | * |
117 | * void someConstMethod() const { |
118 | * // Can call constFunc_. |
119 | * constFunc_(); |
120 | * // However, cannot call func_ because a non-const method cannot |
121 | * // be called from a const one. |
122 | * } |
123 | * }; |
124 | * |
125 | * As you can see, whether the `folly::Function`'s function type should |
126 | * be declared const or not is identical to whether a corresponding method |
127 | * would be declared const or not. |
128 | * |
129 | * You only require a `folly::Function` to hold a const function type, if you |
130 | * intend to invoke it from within a const context. This is to ensure that |
131 | * you cannot mutate its inner state when calling in a const context. |
132 | * |
133 | * This is how the const/non-const choice relates to lambda functions: |
134 | * |
135 | * // Non-mutable lambdas: can be stored in a non-const... |
136 | * folly::Function<void(int)> print_number = |
137 | * [] (int number) { std::cout << number << std::endl; }; |
138 | * |
139 | * // ...as well as in a const folly::Function |
140 | * folly::Function<void(int) const> print_number_const = |
141 | * [] (int number) { std::cout << number << std::endl; }; |
142 | * |
143 | * // Mutable lambda: can only be stored in a non-const folly::Function: |
144 | * int number = 0; |
145 | * folly::Function<void()> print_number = |
146 | * [number] () mutable { std::cout << ++number << std::endl; }; |
147 | * // Trying to store the above mutable lambda in a |
148 | * // `folly::Function<void() const>` would lead to a compiler error: |
149 | * // error: no viable conversion from '(lambda at ...)' to |
150 | * // 'folly::Function<void () const>' |
151 | * |
152 | * Casting between const and non-const `folly::Function`s: |
153 | * conversion from const to non-const signatures happens implicitly. Any |
154 | * function that takes a `folly::Function<R(Args...)>` can be passed |
155 | * a `folly::Function<R(Args...) const>` without explicit conversion. |
156 | * This is safe, because casting from const to non-const only entails giving |
157 | * up the ability to invoke the function from a const context. |
158 | * Casting from a non-const to a const signature is potentially dangerous, |
159 | * as it means that a function that may change its inner state when invoked |
160 | * is made possible to call from a const context. Therefore this cast does |
161 | * not happen implicitly. The function `folly::constCastFunction` can |
162 | * be used to perform the cast. |
163 | * |
164 | * // Mutable lambda: can only be stored in a non-const folly::Function: |
165 | * int number = 0; |
166 | * folly::Function<void()> print_number = |
167 | * [number] () mutable { std::cout << ++number << std::endl; }; |
168 | * |
169 | * // const-cast to a const folly::Function: |
170 | * folly::Function<void() const> print_number_const = |
171 | * constCastFunction(std::move(print_number)); |
172 | * |
173 | * When to use const function types? |
174 | * Generally, only when you need them. When you use a `folly::Function` as a |
175 | * member of a struct or class, only use a const function signature when you |
176 | * need to invoke the function from const context. |
177 | * When passing a `folly::Function` to a function, the function should accept |
178 | * a non-const `folly::Function` whenever possible, i.e. when it does not |
179 | * need to pass on or store a const `folly::Function`. This is the least |
180 | * possible constraint: you can always pass a const `folly::Function` when |
181 | * the function accepts a non-const one. |
182 | * |
183 | * How does the const behaviour compare to `std::function`? |
184 | * `std::function` can wrap object with non-const invokation behaviour but |
185 | * exposes them as const. The equivalent behaviour can be achieved with |
186 | * `folly::Function` like so: |
187 | * |
188 | * std::function<void(void)> stdfunc = someCallable; |
189 | * |
190 | * folly::Function<void(void) const> uniqfunc = constCastFunction( |
191 | * folly::Function<void(void)>(someCallable) |
192 | * ); |
193 | * |
194 | * You need to wrap the callable first in a non-const `folly::Function` to |
195 | * select a non-const invoke operator (or the const one if no non-const one is |
196 | * present), and then move it into a const `folly::Function` using |
197 | * `constCastFunction`. |
198 | * The name of `constCastFunction` should warn you that something |
199 | * potentially dangerous is happening. As a matter of fact, using |
200 | * `std::function` always involves this potentially dangerous aspect, which |
201 | * is why it is not considered fully const-safe or even const-correct. |
202 | * However, in most of the cases you will not need the dangerous aspect at all. |
203 | * Either you do not require invokation of the function from a const context, |
204 | * in which case you do not need to use `constCastFunction` and just |
205 | * use the inner `folly::Function` in the example above, i.e. just use a |
206 | * non-const `folly::Function`. Or, you may need invokation from const, but |
207 | * the callable you are wrapping does not mutate its state (e.g. it is a class |
208 | * object and implements `operator() const`, or it is a normal, |
209 | * non-mutable lambda), in which case you can wrap the callable in a const |
210 | * `folly::Function` directly, without using `constCastFunction`. |
211 | * Only if you require invokation from a const context of a callable that |
212 | * may mutate itself when invoked you have to go through the above procedure. |
213 | * However, in that case what you do is potentially dangerous and requires |
214 | * the equivalent of a `const_cast`, hence you need to call |
215 | * `constCastFunction`. |
216 | */ |
217 | |
218 | #pragma once |
219 | |
220 | #include <functional> |
221 | #include <memory> |
222 | #include <new> |
223 | #include <type_traits> |
224 | #include <utility> |
225 | |
226 | #include <folly/CppAttributes.h> |
227 | #include <folly/Portability.h> |
228 | #include <folly/Traits.h> |
229 | #include <folly/functional/Invoke.h> |
230 | #include <folly/lang/Exception.h> |
231 | |
232 | namespace folly { |
233 | |
234 | template <typename FunctionType> |
235 | class Function; |
236 | |
237 | template <typename ReturnType, typename... Args> |
238 | Function<ReturnType(Args...) const> constCastFunction( |
239 | Function<ReturnType(Args...)>&&) noexcept; |
240 | |
241 | #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE |
242 | template <typename ReturnType, typename... Args> |
243 | Function<ReturnType(Args...) const noexcept> constCastFunction( |
244 | Function<ReturnType(Args...) noexcept>&&) noexcept; |
245 | #endif |
246 | |
247 | namespace detail { |
248 | namespace function { |
249 | |
250 | enum class Op { MOVE, NUKE, HEAP }; |
251 | |
252 | union Data { |
253 | Data() {} |
254 | void* big; |
255 | std::aligned_storage<6 * sizeof(void*)>::type tiny; |
256 | }; |
257 | |
258 | template <typename Fun, typename = Fun*> |
259 | using IsSmall = Conjunction< |
260 | bool_constant<(sizeof(Fun) <= sizeof(Data::tiny))>, |
261 | std::is_nothrow_move_constructible<Fun>>; |
262 | using SmallTag = std::true_type; |
263 | using HeapTag = std::false_type; |
264 | |
265 | template <typename T> |
266 | struct NotFunction : std::true_type {}; |
267 | template <typename T> |
268 | struct NotFunction<Function<T>> : std::false_type {}; |
269 | |
270 | template <typename T> |
271 | using EnableIfNotFunction = |
272 | typename std::enable_if<NotFunction<T>::value>::type; |
273 | |
274 | struct CoerceTag {}; |
275 | |
276 | template <typename, typename T> |
277 | struct IsFunctionNullptrTestable : std::false_type {}; |
278 | |
279 | template <typename T> |
280 | struct IsFunctionNullptrTestable< |
281 | void_t<decltype( |
282 | static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr))>, |
283 | T> : std::true_type {}; |
284 | |
285 | template <typename T> |
286 | constexpr std::enable_if_t< // |
287 | !IsFunctionNullptrTestable<void, T>::value, |
288 | std::false_type> |
289 | isEmptyFunction(T const&) { |
290 | return {}; |
291 | } |
292 | template <typename T> |
293 | constexpr std::enable_if_t<IsFunctionNullptrTestable<void, T>::value, bool> |
294 | isEmptyFunction(T const& t) { |
295 | return static_cast<bool>(t == nullptr); |
296 | } |
297 | |
298 | template <typename F, typename... Args> |
299 | using CallableResult = decltype(std::declval<F>()(std::declval<Args>()...)); |
300 | |
301 | template < |
302 | typename From, |
303 | typename To, |
304 | typename = typename std::enable_if< |
305 | !std::is_reference<To>::value || std::is_reference<From>::value>::type> |
306 | using SafeResultOf = decltype(static_cast<To>(std::declval<From>())); |
307 | |
308 | template <typename F, typename R, typename... A> |
309 | class FunctionTraitsSharedProxy { |
310 | std::shared_ptr<Function<F>> sp_; |
311 | |
312 | public: |
313 | explicit FunctionTraitsSharedProxy(std::nullptr_t) noexcept {} |
314 | explicit FunctionTraitsSharedProxy(Function<F>&& func) |
315 | : sp_(std::make_shared<Function<F>>(std::move(func))) {} |
316 | R operator()(A&&... args) const { |
317 | return (*sp_)(static_cast<A&&>(args)...); |
318 | } |
319 | |
320 | friend bool operator==( |
321 | FunctionTraitsSharedProxy<F, R, A...> const& proxy, |
322 | std::nullptr_t) noexcept { |
323 | return proxy.sp_ == nullptr; |
324 | } |
325 | friend bool operator!=( |
326 | FunctionTraitsSharedProxy<F, R, A...> const& proxy, |
327 | std::nullptr_t) noexcept { |
328 | return proxy.sp_ != nullptr; |
329 | } |
330 | |
331 | friend bool operator==( |
332 | std::nullptr_t, |
333 | FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept { |
334 | return proxy.sp_ == nullptr; |
335 | } |
336 | friend bool operator!=( |
337 | std::nullptr_t, |
338 | FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept { |
339 | return proxy.sp_ != nullptr; |
340 | } |
341 | }; |
342 | |
343 | template <typename FunctionType> |
344 | struct FunctionTraits; |
345 | |
346 | template <typename ReturnType, typename... Args> |
347 | struct FunctionTraits<ReturnType(Args...)> { |
348 | using Call = ReturnType (*)(Data&, Args&&...); |
349 | using IsConst = std::false_type; |
350 | using ConstSignature = ReturnType(Args...) const; |
351 | using NonConstSignature = ReturnType(Args...); |
352 | using OtherSignature = ConstSignature; |
353 | |
354 | template <typename F> |
355 | using ResultOf = |
356 | SafeResultOf<CallableResult<std::decay_t<F>&, Args...>, ReturnType>; |
357 | |
358 | template <typename Fun> |
359 | static ReturnType callSmall(Data& p, Args&&... args) { |
360 | return static_cast<ReturnType>((*static_cast<Fun*>( |
361 | static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); |
362 | } |
363 | |
364 | template <typename Fun> |
365 | static ReturnType callBig(Data& p, Args&&... args) { |
366 | return static_cast<ReturnType>( |
367 | (*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...)); |
368 | } |
369 | |
370 | static ReturnType uninitCall(Data&, Args&&...) { |
371 | throw_exception<std::bad_function_call>(); |
372 | } |
373 | |
374 | ReturnType operator()(Args... args) { |
375 | auto& fn = *static_cast<Function<NonConstSignature>*>(this); |
376 | return fn.call_(fn.data_, static_cast<Args&&>(args)...); |
377 | } |
378 | |
379 | using SharedProxy = |
380 | FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>; |
381 | }; |
382 | |
383 | template <typename ReturnType, typename... Args> |
384 | struct FunctionTraits<ReturnType(Args...) const> { |
385 | using Call = ReturnType (*)(Data&, Args&&...); |
386 | using IsConst = std::true_type; |
387 | using ConstSignature = ReturnType(Args...) const; |
388 | using NonConstSignature = ReturnType(Args...); |
389 | using OtherSignature = NonConstSignature; |
390 | |
391 | template <typename F> |
392 | using ResultOf = |
393 | SafeResultOf<CallableResult<const std::decay_t<F>&, Args...>, ReturnType>; |
394 | |
395 | template <typename Fun> |
396 | static ReturnType callSmall(Data& p, Args&&... args) { |
397 | return static_cast<ReturnType>((*static_cast<const Fun*>( |
398 | static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); |
399 | } |
400 | |
401 | template <typename Fun> |
402 | static ReturnType callBig(Data& p, Args&&... args) { |
403 | return static_cast<ReturnType>( |
404 | (*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...)); |
405 | } |
406 | |
407 | static ReturnType uninitCall(Data&, Args&&...) { |
408 | throw_exception<std::bad_function_call>(); |
409 | } |
410 | |
411 | ReturnType operator()(Args... args) const { |
412 | auto& fn = *static_cast<const Function<ConstSignature>*>(this); |
413 | return fn.call_(fn.data_, static_cast<Args&&>(args)...); |
414 | } |
415 | |
416 | using SharedProxy = |
417 | FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>; |
418 | }; |
419 | |
420 | #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE |
421 | template <typename ReturnType, typename... Args> |
422 | struct FunctionTraits<ReturnType(Args...) noexcept> { |
423 | using Call = ReturnType (*)(Data&, Args&&...) noexcept; |
424 | using IsConst = std::false_type; |
425 | using ConstSignature = ReturnType(Args...) const noexcept; |
426 | using NonConstSignature = ReturnType(Args...) noexcept; |
427 | using OtherSignature = ConstSignature; |
428 | |
429 | template <typename F> |
430 | using ResultOf = |
431 | SafeResultOf<CallableResult<std::decay_t<F>&, Args...>, ReturnType>; |
432 | |
433 | template <typename Fun> |
434 | static ReturnType callSmall(Data& p, Args&&... args) noexcept { |
435 | return static_cast<ReturnType>((*static_cast<Fun*>( |
436 | static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); |
437 | } |
438 | |
439 | template <typename Fun> |
440 | static ReturnType callBig(Data& p, Args&&... args) noexcept { |
441 | return static_cast<ReturnType>( |
442 | (*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...)); |
443 | } |
444 | |
445 | static ReturnType uninitCall(Data&, Args&&...) noexcept { |
446 | terminate_with<std::bad_function_call>(); |
447 | } |
448 | |
449 | ReturnType operator()(Args... args) noexcept { |
450 | auto& fn = *static_cast<Function<NonConstSignature>*>(this); |
451 | return fn.call_(fn.data_, static_cast<Args&&>(args)...); |
452 | } |
453 | |
454 | using SharedProxy = |
455 | FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>; |
456 | }; |
457 | |
458 | template <typename ReturnType, typename... Args> |
459 | struct FunctionTraits<ReturnType(Args...) const noexcept> { |
460 | using Call = ReturnType (*)(Data&, Args&&...) noexcept; |
461 | using IsConst = std::true_type; |
462 | using ConstSignature = ReturnType(Args...) const noexcept; |
463 | using NonConstSignature = ReturnType(Args...) noexcept; |
464 | using OtherSignature = NonConstSignature; |
465 | |
466 | template <typename F> |
467 | using ResultOf = |
468 | SafeResultOf<CallableResult<const std::decay_t<F>&, Args...>, ReturnType>; |
469 | |
470 | template <typename Fun> |
471 | static ReturnType callSmall(Data& p, Args&&... args) noexcept { |
472 | return static_cast<ReturnType>((*static_cast<const Fun*>( |
473 | static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...)); |
474 | } |
475 | |
476 | template <typename Fun> |
477 | static ReturnType callBig(Data& p, Args&&... args) noexcept { |
478 | return static_cast<ReturnType>( |
479 | (*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...)); |
480 | } |
481 | |
482 | static ReturnType uninitCall(Data&, Args&&...) noexcept { |
483 | throw_exception<std::bad_function_call>(); |
484 | } |
485 | |
486 | ReturnType operator()(Args... args) const noexcept { |
487 | auto& fn = *static_cast<const Function<ConstSignature>*>(this); |
488 | return fn.call_(fn.data_, static_cast<Args&&>(args)...); |
489 | } |
490 | |
491 | using SharedProxy = |
492 | FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>; |
493 | }; |
494 | #endif |
495 | |
496 | template <typename Fun> |
497 | bool execSmall(Op o, Data* src, Data* dst) { |
498 | switch (o) { |
499 | case Op::MOVE: |
500 | ::new (static_cast<void*>(&dst->tiny)) |
501 | Fun(std::move(*static_cast<Fun*>(static_cast<void*>(&src->tiny)))); |
502 | FOLLY_FALLTHROUGH; |
503 | case Op::NUKE: |
504 | static_cast<Fun*>(static_cast<void*>(&src->tiny))->~Fun(); |
505 | break; |
506 | case Op::HEAP: |
507 | break; |
508 | } |
509 | return false; |
510 | } |
511 | |
512 | template <typename Fun> |
513 | bool execBig(Op o, Data* src, Data* dst) { |
514 | switch (o) { |
515 | case Op::MOVE: |
516 | dst->big = src->big; |
517 | src->big = nullptr; |
518 | break; |
519 | case Op::NUKE: |
520 | delete static_cast<Fun*>(src->big); |
521 | break; |
522 | case Op::HEAP: |
523 | break; |
524 | } |
525 | return true; |
526 | } |
527 | |
528 | } // namespace function |
529 | } // namespace detail |
530 | |
531 | template <typename FunctionType> |
532 | class Function final : private detail::function::FunctionTraits<FunctionType> { |
533 | // These utility types are defined outside of the template to reduce |
534 | // the number of instantiations, and then imported in the class |
535 | // namespace for convenience. |
536 | using Data = detail::function::Data; |
537 | using Op = detail::function::Op; |
538 | using SmallTag = detail::function::SmallTag; |
539 | using HeapTag = detail::function::HeapTag; |
540 | using CoerceTag = detail::function::CoerceTag; |
541 | |
542 | using Traits = detail::function::FunctionTraits<FunctionType>; |
543 | using Call = typename Traits::Call; |
544 | using Exec = bool (*)(Op, Data*, Data*); |
545 | |
546 | template <typename Fun> |
547 | using IsSmall = detail::function::IsSmall<Fun>; |
548 | |
549 | // The `data_` member is mutable to allow `constCastFunction` to work without |
550 | // invoking undefined behavior. Const-correctness is only violated when |
551 | // `FunctionType` is a const function type (e.g., `int() const`) and `*this` |
552 | // is the result of calling `constCastFunction`. |
553 | mutable Data data_{}; |
554 | Call call_{&Traits::uninitCall}; |
555 | Exec exec_{nullptr}; |
556 | |
557 | bool exec(Op o, Data* src, Data* dst) const { |
558 | return exec_ && exec_(o, src, dst); |
559 | } |
560 | |
561 | friend Traits; |
562 | friend Function<typename Traits::ConstSignature> folly::constCastFunction<>( |
563 | Function<typename Traits::NonConstSignature>&&) noexcept; |
564 | friend class Function<typename Traits::OtherSignature>; |
565 | |
566 | template <typename Fun> |
567 | Function(Fun&& fun, SmallTag) noexcept { |
568 | using FunT = typename std::decay<Fun>::type; |
569 | if (!detail::function::isEmptyFunction(fun)) { |
570 | ::new (static_cast<void*>(&data_.tiny)) FunT(static_cast<Fun&&>(fun)); |
571 | call_ = &Traits::template callSmall<FunT>; |
572 | exec_ = &detail::function::execSmall<FunT>; |
573 | } |
574 | } |
575 | |
576 | template <typename Fun> |
577 | Function(Fun&& fun, HeapTag) { |
578 | using FunT = typename std::decay<Fun>::type; |
579 | if (!detail::function::isEmptyFunction(fun)) { |
580 | data_.big = new FunT(static_cast<Fun&&>(fun)); |
581 | call_ = &Traits::template callBig<FunT>; |
582 | exec_ = &detail::function::execBig<FunT>; |
583 | } |
584 | } |
585 | |
586 | template <typename Signature> |
587 | Function(Function<Signature>&& that, CoerceTag) |
588 | : Function(static_cast<Function<Signature>&&>(that), HeapTag{}) {} |
589 | |
590 | Function(Function<typename Traits::OtherSignature>&& that, CoerceTag) noexcept |
591 | : call_(that.call_), exec_(that.exec_) { |
592 | that.call_ = &Traits::uninitCall; |
593 | that.exec_ = nullptr; |
594 | exec(Op::MOVE, &that.data_, &data_); |
595 | } |
596 | |
597 | public: |
598 | /** |
599 | * Default constructor. Constructs an empty Function. |
600 | */ |
601 | Function() = default; |
602 | |
603 | // not copyable |
604 | Function(const Function&) = delete; |
605 | |
606 | #if __OBJC__ |
607 | // Make sure Objective C blocks are copied |
608 | template <class ReturnType, class... Args> |
609 | /*implicit*/ Function(ReturnType (^objCBlock)(Args... args)) |
610 | : Function([blockCopy = (ReturnType(^)(Args...))[objCBlock copy]]( |
611 | Args... args) { return blockCopy(args...); }){}; |
612 | #endif |
613 | |
614 | /** |
615 | * Move constructor |
616 | */ |
617 | Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) { |
618 | // that must be uninitialized before exec() call in the case of self move |
619 | that.call_ = &Traits::uninitCall; |
620 | that.exec_ = nullptr; |
621 | exec(Op::MOVE, &that.data_, &data_); |
622 | } |
623 | |
624 | /** |
625 | * Constructs an empty `Function`. |
626 | */ |
627 | /* implicit */ Function(std::nullptr_t) noexcept {} |
628 | |
629 | /** |
630 | * Constructs a new `Function` from any callable object that is _not_ a |
631 | * `folly::Function`. This handles function pointers, pointers to static |
632 | * member functions, `std::reference_wrapper` objects, `std::function` |
633 | * objects, and arbitrary objects that implement `operator()` if the parameter |
634 | * signature matches (i.e. it returns an object convertible to `R` when called |
635 | * with `Args...`). |
636 | * |
637 | * \note `typename Traits::template ResultOf<Fun>` prevents this overload |
638 | * from being selected by overload resolution when `fun` is not a compatible |
639 | * function. |
640 | * |
641 | * \note The noexcept requires some explanation. `IsSmall` is true when the |
642 | * decayed type fits within the internal buffer and is noexcept-movable. But |
643 | * this ctor might copy, not move. What we need here, if this ctor does a |
644 | * copy, is that this ctor be noexcept when the copy is noexcept. That is not |
645 | * checked in `IsSmall`, and shouldn't be, because once the `Function` is |
646 | * constructed, the contained object is never copied. This check is for this |
647 | * ctor only, in the case that this ctor does a copy. |
648 | */ |
649 | template < |
650 | typename Fun, |
651 | typename = detail::function::EnableIfNotFunction<Fun>, |
652 | typename = typename Traits::template ResultOf<Fun>> |
653 | /* implicit */ Function(Fun fun) noexcept( |
654 | IsSmall<Fun>::value&& noexcept(Fun(std::declval<Fun>()))) |
655 | : Function(std::move(fun), IsSmall<Fun>{}) {} |
656 | |
657 | /** |
658 | * For move-constructing from a `folly::Function<X(Ys...) [const?]>`. |
659 | * For a `Function` with a `const` function type, the object must be |
660 | * callable from a `const`-reference, i.e. implement `operator() const`. |
661 | * For a `Function` with a non-`const` function type, the object will |
662 | * be called from a non-const reference, which means that it will execute |
663 | * a non-const `operator()` if it is defined, and falls back to |
664 | * `operator() const` otherwise. |
665 | */ |
666 | template < |
667 | typename Signature, |
668 | typename = typename Traits::template ResultOf<Function<Signature>>> |
669 | Function(Function<Signature>&& that) noexcept( |
670 | noexcept(Function(std::move(that), CoerceTag{}))) |
671 | : Function(std::move(that), CoerceTag{}) {} |
672 | |
673 | /** |
674 | * If `ptr` is null, constructs an empty `Function`. Otherwise, |
675 | * this constructor is equivalent to `Function(std::mem_fn(ptr))`. |
676 | */ |
677 | template < |
678 | typename Member, |
679 | typename Class, |
680 | // Prevent this overload from being selected when `ptr` is not a |
681 | // compatible member function pointer. |
682 | typename = decltype(Function(std::mem_fn((Member Class::*)0)))> |
683 | /* implicit */ Function(Member Class::*ptr) noexcept { |
684 | if (ptr) { |
685 | *this = std::mem_fn(ptr); |
686 | } |
687 | } |
688 | |
689 | ~Function() { |
690 | exec(Op::NUKE, &data_, nullptr); |
691 | } |
692 | |
693 | Function& operator=(const Function&) = delete; |
694 | |
695 | #if __OBJC__ |
696 | // Make sure Objective C blocks are copied |
697 | template <class ReturnType, class... Args> |
698 | /* implicit */ Function& operator=(ReturnType (^objCBlock)(Args... args)) { |
699 | (*this) = [blockCopy = (ReturnType(^)(Args...))[objCBlock copy]]( |
700 | Args... args) { return blockCopy(args...); }; |
701 | return *this; |
702 | } |
703 | #endif |
704 | |
705 | /** |
706 | * Move assignment operator |
707 | * |
708 | * \note Leaves `that` in a valid but unspecified state. If `&that == this` |
709 | * then `*this` is left in a valid but unspecified state. |
710 | */ |
711 | Function& operator=(Function&& that) noexcept { |
712 | // Q: Why is it safe to destroy and reconstruct this object in place? |
713 | // A: Two reasons: First, `Function` is a final class, so in doing this |
714 | // we aren't slicing off any derived parts. And second, the move |
715 | // operation is guaranteed not to throw so we always leave the object |
716 | // in a valid state. |
717 | // In the case of self-move (this == &that), this leaves the object in |
718 | // a default-constructed state. First the object is destroyed, then we |
719 | // pass the destroyed object to the move constructor. The first thing the |
720 | // move constructor does is default-construct the object. That object is |
721 | // "moved" into itself, which is a no-op for a default-constructed Function. |
722 | this->~Function(); |
723 | ::new (this) Function(std::move(that)); |
724 | return *this; |
725 | } |
726 | |
727 | /** |
728 | * Assigns a callable object to this `Function`. If the operation fails, |
729 | * `*this` is left unmodified. |
730 | * |
731 | * \note `typename = decltype(Function(std::declval<Fun>()))` prevents this |
732 | * overload from being selected by overload resolution when `fun` is not a |
733 | * compatible function. |
734 | */ |
735 | template <typename Fun, typename = decltype(Function(std::declval<Fun>()))> |
736 | Function& operator=(Fun fun) noexcept( |
737 | noexcept(/* implicit */ Function(std::declval<Fun>()))) { |
738 | // Doing this in place is more efficient when we can do so safely. |
739 | if (noexcept(/* implicit */ Function(std::declval<Fun>()))) { |
740 | // Q: Why is is safe to destroy and reconstruct this object in place? |
741 | // A: See the explanation in the move assignment operator. |
742 | this->~Function(); |
743 | ::new (this) Function(std::move(fun)); |
744 | } else { |
745 | // Construct a temporary and (nothrow) swap. |
746 | Function(std::move(fun)).swap(*this); |
747 | } |
748 | return *this; |
749 | } |
750 | |
751 | /** |
752 | * For assigning from a `Function<X(Ys..) [const?]>`. |
753 | */ |
754 | template < |
755 | typename Signature, |
756 | typename = typename Traits::template ResultOf<Function<Signature>>> |
757 | Function& operator=(Function<Signature>&& that) noexcept( |
758 | noexcept(Function(std::move(that)))) { |
759 | return (*this = Function(std::move(that))); |
760 | } |
761 | |
762 | /** |
763 | * Clears this `Function`. |
764 | */ |
765 | Function& operator=(std::nullptr_t) noexcept { |
766 | return (*this = Function()); |
767 | } |
768 | |
769 | /** |
770 | * If `ptr` is null, clears this `Function`. Otherwise, this assignment |
771 | * operator is equivalent to `*this = std::mem_fn(ptr)`. |
772 | */ |
773 | template <typename Member, typename Class> |
774 | auto operator=(Member Class::*ptr) noexcept |
775 | // Prevent this overload from being selected when `ptr` is not a |
776 | // compatible member function pointer. |
777 | -> decltype(operator=(std::mem_fn(ptr))) { |
778 | return ptr ? (*this = std::mem_fn(ptr)) : (*this = Function()); |
779 | } |
780 | |
781 | /** |
782 | * Call the wrapped callable object with the specified arguments. |
783 | */ |
784 | using Traits::operator(); |
785 | |
786 | /** |
787 | * Exchanges the callable objects of `*this` and `that`. |
788 | */ |
789 | void swap(Function& that) noexcept { |
790 | std::swap(*this, that); |
791 | } |
792 | |
793 | /** |
794 | * Returns `true` if this `Function` contains a callable, i.e. is |
795 | * non-empty. |
796 | */ |
797 | explicit operator bool() const noexcept { |
798 | return exec_ != nullptr; |
799 | } |
800 | |
801 | /** |
802 | * Returns `true` if this `Function` stores the callable on the |
803 | * heap. If `false` is returned, there has been no additional memory |
804 | * allocation and the callable is stored inside the `Function` |
805 | * object itself. |
806 | */ |
807 | bool hasAllocatedMemory() const noexcept { |
808 | return exec(Op::HEAP, nullptr, nullptr); |
809 | } |
810 | |
811 | using typename Traits::SharedProxy; |
812 | |
813 | /** |
814 | * Move this `Function` into a copyable callable object, of which all copies |
815 | * share the state. |
816 | */ |
817 | SharedProxy asSharedProxy() && { |
818 | return SharedProxy{std::move(*this)}; |
819 | } |
820 | |
821 | /** |
822 | * Construct a `std::function` by moving in the contents of this `Function`. |
823 | * Note that the returned `std::function` will share its state (i.e. captured |
824 | * data) across all copies you make of it, so be very careful when copying. |
825 | */ |
826 | std::function<typename Traits::NonConstSignature> asStdFunction() && { |
827 | return std::move(*this).asSharedProxy(); |
828 | } |
829 | }; |
830 | |
831 | template <typename FunctionType> |
832 | void swap(Function<FunctionType>& lhs, Function<FunctionType>& rhs) noexcept { |
833 | lhs.swap(rhs); |
834 | } |
835 | |
836 | template <typename FunctionType> |
837 | bool operator==(const Function<FunctionType>& fn, std::nullptr_t) { |
838 | return !fn; |
839 | } |
840 | |
841 | template <typename FunctionType> |
842 | bool operator==(std::nullptr_t, const Function<FunctionType>& fn) { |
843 | return !fn; |
844 | } |
845 | |
846 | template <typename FunctionType> |
847 | bool operator!=(const Function<FunctionType>& fn, std::nullptr_t) { |
848 | return !(fn == nullptr); |
849 | } |
850 | |
851 | template <typename FunctionType> |
852 | bool operator!=(std::nullptr_t, const Function<FunctionType>& fn) { |
853 | return !(nullptr == fn); |
854 | } |
855 | |
856 | /** |
857 | * NOTE: See detailed note about `constCastFunction` at the top of the file. |
858 | * This is potentially dangerous and requires the equivalent of a `const_cast`. |
859 | */ |
860 | template <typename ReturnType, typename... Args> |
861 | Function<ReturnType(Args...) const> constCastFunction( |
862 | Function<ReturnType(Args...)>&& that) noexcept { |
863 | return Function<ReturnType(Args...) const>{std::move(that), |
864 | detail::function::CoerceTag{}}; |
865 | } |
866 | |
867 | template <typename ReturnType, typename... Args> |
868 | Function<ReturnType(Args...) const> constCastFunction( |
869 | Function<ReturnType(Args...) const>&& that) noexcept { |
870 | return std::move(that); |
871 | } |
872 | |
873 | #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE |
874 | template <typename ReturnType, typename... Args> |
875 | Function<ReturnType(Args...) const noexcept> constCastFunction( |
876 | Function<ReturnType(Args...) noexcept>&& that) noexcept { |
877 | return Function<ReturnType(Args...) const noexcept>{ |
878 | std::move(that), detail::function::CoerceTag{}}; |
879 | } |
880 | |
881 | template <typename ReturnType, typename... Args> |
882 | Function<ReturnType(Args...) const noexcept> constCastFunction( |
883 | Function<ReturnType(Args...) const noexcept>&& that) noexcept { |
884 | return std::move(that); |
885 | } |
886 | #endif |
887 | |
888 | /** |
889 | * @class FunctionRef |
890 | * |
891 | * @brief A reference wrapper for callable objects |
892 | * |
893 | * FunctionRef is similar to std::reference_wrapper, but the template parameter |
894 | * is the function signature type rather than the type of the referenced object. |
895 | * A folly::FunctionRef is cheap to construct as it contains only a pointer to |
896 | * the referenced callable and a pointer to a function which invokes the |
897 | * callable. |
898 | * |
899 | * The user of FunctionRef must be aware of the reference semantics: storing a |
900 | * copy of a FunctionRef is potentially dangerous and should be avoided unless |
901 | * the referenced object definitely outlives the FunctionRef object. Thus any |
902 | * function that accepts a FunctionRef parameter should only use it to invoke |
903 | * the referenced function and not store a copy of it. Knowing that FunctionRef |
904 | * itself has reference semantics, it is generally okay to use it to reference |
905 | * lambdas that capture by reference. |
906 | */ |
907 | |
908 | template <typename FunctionType> |
909 | class FunctionRef; |
910 | |
911 | template <typename ReturnType, typename... Args> |
912 | class FunctionRef<ReturnType(Args...)> final { |
913 | using Call = ReturnType (*)(void*, Args&&...); |
914 | |
915 | static ReturnType uninitCall(void*, Args&&...) { |
916 | throw_exception<std::bad_function_call>(); |
917 | } |
918 | |
919 | template <typename Fun> |
920 | static ReturnType call(void* object, Args&&... args) { |
921 | using Pointer = std::add_pointer_t<Fun>; |
922 | return static_cast<ReturnType>(invoke( |
923 | static_cast<Fun&&>(*static_cast<Pointer>(object)), |
924 | static_cast<Args&&>(args)...)); |
925 | } |
926 | |
927 | void* object_{nullptr}; |
928 | Call call_{&FunctionRef::uninitCall}; |
929 | |
930 | public: |
931 | /** |
932 | * Default constructor. Constructs an empty FunctionRef. |
933 | * |
934 | * Invoking it will throw std::bad_function_call. |
935 | */ |
936 | constexpr FunctionRef() = default; |
937 | |
938 | /** |
939 | * Like default constructor. Constructs an empty FunctionRef. |
940 | * |
941 | * Invoking it will throw std::bad_function_call. |
942 | */ |
943 | constexpr explicit FunctionRef(std::nullptr_t) noexcept {} |
944 | |
945 | /** |
946 | * Construct a FunctionRef from a reference to a callable object. |
947 | */ |
948 | template < |
949 | typename Fun, |
950 | typename std::enable_if< |
951 | Conjunction< |
952 | Negation<std::is_same<FunctionRef, std::decay_t<Fun>>>, |
953 | is_invocable_r<ReturnType, Fun&&, Args&&...>>::value, |
954 | int>::type = 0> |
955 | constexpr /* implicit */ FunctionRef(Fun&& fun) noexcept |
956 | // `Fun` may be a const type, in which case we have to do a const_cast |
957 | // to store the address in a `void*`. This is safe because the `void*` |
958 | // will be cast back to `Fun*` (which is a const pointer whenever `Fun` |
959 | // is a const type) inside `FunctionRef::call` |
960 | : object_( |
961 | const_cast<void*>(static_cast<void const*>(std::addressof(fun)))), |
962 | call_(&FunctionRef::call<Fun>) {} |
963 | |
964 | ReturnType operator()(Args... args) const { |
965 | return call_(object_, static_cast<Args&&>(args)...); |
966 | } |
967 | |
968 | constexpr explicit operator bool() const noexcept { |
969 | return object_; |
970 | } |
971 | |
972 | constexpr friend bool operator==( |
973 | FunctionRef<ReturnType(Args...)> ref, |
974 | std::nullptr_t) noexcept { |
975 | return ref.object_ == nullptr; |
976 | } |
977 | constexpr friend bool operator!=( |
978 | FunctionRef<ReturnType(Args...)> ref, |
979 | std::nullptr_t) noexcept { |
980 | return ref.object_ != nullptr; |
981 | } |
982 | |
983 | constexpr friend bool operator==( |
984 | std::nullptr_t, |
985 | FunctionRef<ReturnType(Args...)> ref) noexcept { |
986 | return ref.object_ == nullptr; |
987 | } |
988 | constexpr friend bool operator!=( |
989 | std::nullptr_t, |
990 | FunctionRef<ReturnType(Args...)> ref) noexcept { |
991 | return ref.object_ != nullptr; |
992 | } |
993 | }; |
994 | |
995 | } // namespace folly |
996 | |