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