]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rocksdb/third-party/folly/folly/synchronization/detail/InlineFunctionRef.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / third-party / folly / folly / synchronization / detail / InlineFunctionRef.h
diff --git a/ceph/src/rocksdb/third-party/folly/folly/synchronization/detail/InlineFunctionRef.h b/ceph/src/rocksdb/third-party/folly/folly/synchronization/detail/InlineFunctionRef.h
deleted file mode 100644 (file)
index 6782c79..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
-//  This source code is licensed under both the GPLv2 (found in the
-//  COPYING file in the root directory) and Apache 2.0 License
-//  (found in the LICENSE.Apache file in the root directory).
-
-#pragma once
-
-#include <cstdint>
-#include <type_traits>
-
-#include <folly/Traits.h>
-#include <folly/Utility.h>
-#include <folly/functional/Invoke.h>
-#include <folly/lang/Launder.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;
-
-template <typename ReturnType, typename... Args, std::size_t Size>
-class InlineFunctionRef<ReturnType(Args...), Size> {
-  using Storage =
-      _t<std::aligned_storage<Size - sizeof(uintptr_t), sizeof(uintptr_t)>>;
-  using Call = ReturnType (*)(const Storage&, Args&&...);
-
-  struct InSituTag {};
-  struct RefTag {};
-
-  static_assert(
-      (Size % sizeof(uintptr_t)) == 0,
-      "Size has to be a multiple of sizeof(uintptr_t)");
-  static_assert(Size >= 2 * sizeof(uintptr_t), "This doesn't work");
-  static_assert(alignof(Call) == alignof(Storage), "Mismatching alignments");
-
-  // This defines a mode tag that is used in the construction of
-  // InlineFunctionRef to determine the storage and indirection method for the
-  // passed callable.
-  //
-  // This requires that the we pass in a type that is not ref-qualified.
-  template <typename Func>
-  using ConstructMode = _t<std::conditional<
-      folly::is_trivially_copyable<Func>{} &&
-          (sizeof(Func) <= sizeof(Storage)) &&
-          (alignof(Func) <= alignof(Storage)),
-      InSituTag,
-      RefTag>>;
-
- public:
-  /**
-   * InlineFunctionRef can be constructed from a nullptr, callable or another
-   * InlineFunctionRef with the same size.  These are the constructors that
-   * don't take a callable.
-   *
-   * InlineFunctionRef is meant to be trivially copyable so we default the
-   * constructors and assignment operators.
-   */
-  InlineFunctionRef(std::nullptr_t) : call_{nullptr} {}
-  InlineFunctionRef() : call_{nullptr} {}
-  InlineFunctionRef(const InlineFunctionRef& other) = default;
-  InlineFunctionRef(InlineFunctionRef&&) = default;
-  InlineFunctionRef& operator=(const InlineFunctionRef&) = default;
-  InlineFunctionRef& operator=(InlineFunctionRef&&) = default;
-
-  /**
-   * Constructors from callables.
-   *
-   * If all of the following conditions are satisfied, then we store the
-   * callable in the inline storage:
-   *
-   *  1) The function has been passed as an rvalue, meaning that there is no
-   *     use of the original in the user's code after it has been passed to
-   *     us.
-   *  2) Size of the callable is less than the size of the inline storage
-   *     buffer.
-   *  3) The callable is trivially constructible and destructible.
-   *
-   * If any one of the above conditions is not satisfied, we fall back to
-   * reference semantics and store the function as a pointer, and add a level
-   * of indirection through type erasure.
-   */
-  template <
-      typename Func,
-      _t<std::enable_if<
-          !std::is_same<_t<std::decay<Func>>, InlineFunctionRef>{} &&
-          !std::is_reference<Func>{} &&
-          std::is_convertible<
-              decltype(std::declval<Func&&>()(std::declval<Args&&>()...)),
-              ReturnType>{}>>* = nullptr>
-  InlineFunctionRef(Func&& func) {
-    // We disallow construction from lvalues, so assert that this is not a
-    // reference type.  When invoked with an lvalue, Func is a lvalue
-    // reference type, when invoked with an rvalue, Func is not ref-qualified.
-    static_assert(
-        !std::is_reference<Func>{},
-        "InlineFunctionRef cannot be used with lvalues");
-    static_assert(std::is_rvalue_reference<Func&&>{}, "");
-    construct(ConstructMode<Func>{}, folly::as_const(func));
-  }
-
-  /**
-   * The call operator uses the function pointer and a reference to the
-   * storage to do the dispatch.  The function pointer takes care of the
-   * appropriate casting.
-   */
-  ReturnType operator()(Args... args) const {
-    return call_(storage_, static_cast<Args&&>(args)...);
-  }
-
-  /**
-   * We have a function engaged if the call function points to anything other
-   * than null.
-   */
-  operator bool() const noexcept {
-    return call_;
-  }
-
- private:
-  friend class InlineFunctionRefTest;
-
-  /**
-   * Inline storage constructor implementation.
-   */
-  template <typename Func>
-  void construct(InSituTag, Func& func) {
-    using Value = _t<std::remove_reference<Func>>;
-
-    // Assert that the following two assumptions are valid
-    //    1) fit in the storage space we have and match alignments, and
-    //    2) be invocable in a const context, it does not make sense to copy a
-    //       callable into inline storage if it makes state local
-    //       modifications.
-    static_assert(alignof(Value) <= alignof(Storage), "");
-    static_assert(is_invocable<const _t<std::decay<Func>>, Args&&...>{}, "");
-    static_assert(folly::is_trivially_copyable<Value>{}, "");
-
-    new (&storage_) Value{func};
-    call_ = &callInline<Value>;
-  }
-
-  /**
-   * Ref storage constructor implementation.  This is identical to
-   * folly::FunctionRef.
-   */
-  template <typename Func>
-  void construct(RefTag, Func& func) {
-    // store a pointer to the function
-    using Pointer = _t<std::add_pointer<_t<std::remove_reference<Func>>>>;
-    new (&storage_) Pointer{&func};
-    call_ = &callPointer<Pointer>;
-  }
-
-  template <typename Func>
-  static ReturnType callInline(const Storage& object, Args&&... args) {
-    // The only type of pointer allowed is a function pointer, no other
-    // pointer types are invocable.
-    static_assert(
-        !std::is_pointer<Func>::value ||
-            std::is_function<_t<std::remove_pointer<Func>>>::value,
-        "");
-    return (*folly::launder(reinterpret_cast<const Func*>(&object)))(
-        static_cast<Args&&>(args)...);
-  }
-
-  template <typename Func>
-  static ReturnType callPointer(const Storage& object, Args&&... args) {
-    // When the function we were instantiated with was not trivial, the given
-    // pointer points to a pointer, which pointers to the callable.  So we
-    // cast to a pointer and then to the pointee.
-    static_assert(std::is_pointer<Func>::value, "");
-    return (**folly::launder(reinterpret_cast<const Func*>(&object)))(
-        static_cast<Args&&>(args)...);
-  }
-
-  Call call_;
-  Storage storage_;
-};
-
-} // namespace detail
-} // namespace folly