/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <new> #include <folly/Function.h> #include <folly/Traits.h> #include <folly/Utility.h> #include <folly/functional/Invoke.h> namespace folly { namespace detail { /** * InlineFunctionRef is similar to folly::FunctionRef but has the additional * benefit of being able to store the function it was instantiated with inline * in a buffer of the given capacity. Inline storage is only used if the * function object and a pointer (for type-erasure) are small enough to fit in * the templated size. If there is not enough in-situ capacity for the * callable, this just stores a reference to the function object like * FunctionRef. * * This helps give a perf boost in the case where the data gets separated from * the point of invocation. If, for example, at the point of invocation, the * InlineFunctionRef object is not cached, a remote memory/cache read might be * required to invoke the original callable. Customizable inline storage * helps tune storage so we can store a type-erased callable with better * performance and locality. A real-life example of this might be a * folly::FunctionRef with a function pointer. The folly::FunctionRef would * point to the function pointer object in a remote location. This causes a * double-indirection at the point of invocation, and if that memory is dirty, * or not cached, it would cause additional cache misses. On the other hand * with InlineFunctionRef, inline storage would store the value of the * function pointer, avoiding the need to do a remote lookup to fetch the * value of the function pointer. * * To prevent misuse, InlineFunctionRef disallows construction from an lvalue * callable. This is to prevent usage where a user relies on the callable's * state after invocation through InlineFunctionRef. This has the potential * to copy the callable into inline storage when the callable is small, so we * might not use the same function when invoking, but rather a copy of it. * * Also note that InlineFunctionRef will always invoke the const qualified * version of the call operator for any callable that is passed. Regardless * of whether it has a non-const version. This is done to enforce the logical * constraint of function state being immutable. * * This class is always trivially-copyable (and therefore * trivially-destructible), making it suitable for use in a union without * requiring manual destruction. */ template <typename FunctionType, std::size_t Size> class InlineFunctionRef; InlineFunctionRef<ReturnType (Args...), Size>; } // namespace detail } // namespace folly