/*
 *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef RTC_BASE_UNTYPED_FUNCTION_H_
#define RTC_BASE_UNTYPED_FUNCTION_H_

#include <cstddef>
#include <cstring>
#include <memory>
#include <type_traits>
#include <utility>

#include "rtc_base/system/assume.h"

namespace webrtc {
namespace webrtc_function_impl {

using FunVoid = void();

// Inline storage size is this many machine words.
enum : size_t { kInlineStorageWords = 4 };

union VoidUnion {
  void* void_ptr;
  FunVoid* fun_ptr;
  typename std::aligned_storage<kInlineStorageWords * sizeof(uintptr_t)>::type
      inline_storage;
};

// Returns the number of elements of the `inline_storage` array required to
// store an object of type T.
template <typename T>
constexpr size_t InlineStorageSize() {
  // sizeof(T) / sizeof(uintptr_t), but rounded up.
  return (sizeof(T) + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
}

template <typename T>
struct CallHelpers;
template <typename RetT, typename... ArgT>
struct CallHelpers<RetT(ArgT...)> {
  // Return type of the three helpers below.
  using return_type = RetT;
  // Complete function type of the three helpers below.
  using function_type = RetT(VoidUnion*, ArgT...);
  // Helper for calling the `void_ptr` case of VoidUnion.
  template <typename F>
  static RetT CallVoidPtr(VoidUnion* vu, ArgT... args) {
    return (*static_cast<F*>(vu->void_ptr))(std::forward<ArgT>(args)...);
  }
  // Helper for calling the `fun_ptr` case of VoidUnion.
  static RetT CallFunPtr(VoidUnion* vu, ArgT... args) {
    return (reinterpret_cast<RetT (*)(ArgT...)>(vu->fun_ptr))(
        std::forward<ArgT>(args)...);
  }
  // Helper for calling the `inline_storage` case of VoidUnion.
  template <typename F>
  static RetT CallInlineStorage(VoidUnion* vu, ArgT... args) {
    return (*reinterpret_cast<F*>(&vu->inline_storage))(
        std::forward<ArgT>(args)...);
  }
};

}  // namespace webrtc_function_impl

// A class that holds (and owns) any callable. The same function call signature
// must be provided when constructing and calling the object.
//
// The point of not having the call signature as a class template parameter is
// to have one single concrete type for all signatures; this reduces binary
// size.
class UntypedFunction final {
 public:
  // Callables of at most this size can be stored inline, if they are trivial.
  // (Useful in tests and benchmarks; avoid using this in production code.)
  enum : size_t {
    kInlineStorageSize = sizeof(webrtc_function_impl::VoidUnion::inline_storage)
  };
  static_assert(kInlineStorageSize ==
                    webrtc_function_impl::kInlineStorageWords *
                        sizeof(uintptr_t),
                "");

  // The *UntypedFunctionArgs structs are used to transfer arguments from
  // PrepareArgs() to Create(). They are trivial, but may own heap allocations,
  // so make sure to pass them to Create() exactly once!
  //
  // The point of doing Create(PrepareArgs(foo)) instead of just Create(foo) is
  // to separate the code that has to be inlined (PrepareArgs) from the code
  // that can be noninlined (Create); the *UntypedFunctionArgs types are
  // designed to efficiently carry the required information from one to the
  // other.
  template <size_t N>
  struct TrivialUntypedFunctionArgs {
    static_assert(N >= 1, "");
    static_assert(N <= webrtc_function_impl::kInlineStorageWords, "");
    // We use an uintptr_t array here instead of std::aligned_storage, because
    // the former can be efficiently passed in registers when using
    // TrivialUntypedFunctionArgs as a function argument. (We can't do the same
    // in VoidUnion, because std::aligned_storage but not uintptr_t can be
    // legally reinterpret_casted to arbitrary types.
    // TrivialUntypedFunctionArgs, on the other hand, only needs to handle
    // placement new and memcpy.)
    alignas(std::max_align_t) uintptr_t inline_storage[N];
    webrtc_function_impl::FunVoid* call;
  };
  struct NontrivialUntypedFunctionArgs {
    void* void_ptr;
    webrtc_function_impl::FunVoid* call;
    void (*del)(webrtc_function_impl::VoidUnion*);
  };
  struct FunctionPointerUntypedFunctionArgs {
    webrtc_function_impl::FunVoid* fun_ptr;
    webrtc_function_impl::FunVoid* call;
  };

  // Create function for lambdas and other callables that are trivial and small;
  // it accepts every type of argument except those noted in its enable_if call.
  template <
      typename Signature,
      typename F,
      typename F_deref = typename std::remove_reference<F>::type,
      typename std::enable_if<
          // Not for function pointers; we have another overload for that below.
          !std::is_function<
              typename std::remove_pointer<F_deref>::type>::value &&

          // Not for nullptr; we have a constructor for that below.
          !std::is_same<std::nullptr_t,
                        typename std::remove_cv<F>::type>::value &&

          // Not for UntypedFunction objects; use move construction or
          // assignment.
          !std::is_same<UntypedFunction,
                        typename std::remove_cv<F_deref>::type>::value &&

          // Only for trivial callables that will fit in inline storage.
          std::is_trivially_move_constructible<F_deref>::value &&
          std::is_trivially_destructible<F_deref>::value &&
          sizeof(F_deref) <= kInlineStorageSize>::type* = nullptr,
      size_t InlineSize = webrtc_function_impl::InlineStorageSize<F_deref>()>
  static TrivialUntypedFunctionArgs<InlineSize> PrepareArgs(F&& f) {
    // The callable is trivial and small enough, so we just store its bytes
    // in the inline storage.
    TrivialUntypedFunctionArgs<InlineSize> args;
    new (&args.inline_storage) F_deref(std::forward<F>(f));
    args.call = reinterpret_cast<webrtc_function_impl::FunVoid*>(
        webrtc_function_impl::CallHelpers<
            Signature>::template CallInlineStorage<F_deref>);
    return args;
  }
  template <size_t InlineSize>
  static UntypedFunction Create(TrivialUntypedFunctionArgs<InlineSize> args) {
    webrtc_function_impl::VoidUnion vu;
    std::memcpy(&vu.inline_storage, args.inline_storage,
                sizeof(args.inline_storage));
    return UntypedFunction(vu, args.call, nullptr);
  }

  // Create function for lambdas and other callables that are nontrivial or
  // large; it accepts every type of argument except those noted in its
  // enable_if call.
  template <typename Signature,
            typename F,
            typename F_deref = typename std::remove_reference<F>::type,
            typename std::enable_if<
                // Not for function pointers; we have another overload for that
                // below.
                !std::is_function<
                    typename std::remove_pointer<F_deref>::type>::value &&

                // Not for nullptr; we have a constructor for that below.
                !std::is_same<std::nullptr_t,
                              typename std::remove_cv<F>::type>::value &&

                // Not for UntypedFunction objects; use move construction or
                // assignment.
                !std::is_same<UntypedFunction,
                              typename std::remove_cv<F_deref>::type>::value &&

                // Only for nontrivial callables, or callables that won't fit in
                // inline storage.
                !(std::is_trivially_move_constructible<F_deref>::value &&
                  std::is_trivially_destructible<F_deref>::value &&
                  sizeof(F_deref) <= kInlineStorageSize)>::type* = nullptr>
  static NontrivialUntypedFunctionArgs PrepareArgs(F&& f) {
    // The callable is either nontrivial or too large, so we can't keep it
    // in the inline storage; use the heap instead.
    NontrivialUntypedFunctionArgs args;
    args.void_ptr = new F_deref(std::forward<F>(f));
    args.call = reinterpret_cast<webrtc_function_impl::FunVoid*>(
        webrtc_function_impl::CallHelpers<Signature>::template CallVoidPtr<
            F_deref>);
    args.del = static_cast<void (*)(webrtc_function_impl::VoidUnion*)>(
        [](webrtc_function_impl::VoidUnion* vu) {
          // Assuming that this pointer isn't null allows the
          // compiler to eliminate a null check in the (inlined)
          // delete operation.
          RTC_ASSUME(vu->void_ptr != nullptr);
          delete reinterpret_cast<F_deref*>(vu->void_ptr);
        });
    return args;
  }
  static UntypedFunction Create(NontrivialUntypedFunctionArgs args) {
    webrtc_function_impl::VoidUnion vu;
    vu.void_ptr = args.void_ptr;
    return UntypedFunction(vu, args.call, args.del);
  }

  // Create function that accepts function pointers. If the argument is null,
  // the result is an empty UntypedFunction.
  template <typename Signature>
  static FunctionPointerUntypedFunctionArgs PrepareArgs(Signature* f) {
    FunctionPointerUntypedFunctionArgs args;
    args.fun_ptr = reinterpret_cast<webrtc_function_impl::FunVoid*>(f);
    args.call = reinterpret_cast<webrtc_function_impl::FunVoid*>(
        webrtc_function_impl::CallHelpers<Signature>::CallFunPtr);
    return args;
  }
  static UntypedFunction Create(FunctionPointerUntypedFunctionArgs args) {
    webrtc_function_impl::VoidUnion vu;
    vu.fun_ptr = args.fun_ptr;
    return UntypedFunction(vu, args.fun_ptr == nullptr ? nullptr : args.call,
                           nullptr);
  }

  // Prepares arguments and creates an UntypedFunction in one go.
  template <typename Signature, typename F>
  static UntypedFunction Create(F&& f) {
    return Create(PrepareArgs<Signature>(std::forward<F>(f)));
  }

  // Default constructor. Creates an empty UntypedFunction.
  UntypedFunction() : call_(nullptr), delete_(nullptr) {}

  // Nullptr constructor and assignment. Creates an empty UntypedFunction.
  UntypedFunction(std::nullptr_t)  // NOLINT(runtime/explicit)
      : call_(nullptr), delete_(nullptr) {}
  UntypedFunction& operator=(std::nullptr_t) {
    call_ = nullptr;
    if (delete_) {
      delete_(&f_);
      delete_ = nullptr;
    }
    return *this;
  }

  // Not copyable.
  UntypedFunction(const UntypedFunction&) = delete;
  UntypedFunction& operator=(const UntypedFunction&) = delete;

  // Move construction and assignment.
  UntypedFunction(UntypedFunction&& other)
      : f_(other.f_), call_(other.call_), delete_(other.delete_) {
    other.delete_ = nullptr;
  }
  UntypedFunction& operator=(UntypedFunction&& other) {
    if (delete_) {
      delete_(&f_);
    }
    f_ = other.f_;
    call_ = other.call_;
    delete_ = other.delete_;
    other.delete_ = nullptr;
    return *this;
  }

  ~UntypedFunction() {
    if (delete_) {
      delete_(&f_);
    }
  }

  friend void swap(UntypedFunction& a, UntypedFunction& b) {
    using std::swap;
    swap(a.f_, b.f_);
    swap(a.call_, b.call_);
    swap(a.delete_, b.delete_);
  }

  // Returns true if we have a function, false if we don't (i.e., we're null).
  explicit operator bool() const { return call_ != nullptr; }

  template <typename Signature, typename... ArgT>
  typename webrtc_function_impl::CallHelpers<Signature>::return_type Call(
      ArgT&&... args) {
    return reinterpret_cast<
        typename webrtc_function_impl::CallHelpers<Signature>::function_type*>(
        call_)(&f_, std::forward<ArgT>(args)...);
  }

  // Returns true iff we don't need to call a destructor. This is guaranteed
  // to hold for a moved-from object.
  bool IsTriviallyDestructible() { return delete_ == nullptr; }

 private:
  UntypedFunction(webrtc_function_impl::VoidUnion f,
                  webrtc_function_impl::FunVoid* call,
                  void (*del)(webrtc_function_impl::VoidUnion*))
      : f_(f), call_(call), delete_(del) {}

  // The callable thing, or a pointer to it.
  webrtc_function_impl::VoidUnion f_;

  // Pointer to a dispatch function that knows the type of the callable thing
  // that's stored in f_, and how to call it. An UntypedFunction object is empty
  // (null) iff call_ is null.
  webrtc_function_impl::FunVoid* call_;

  // Pointer to a function that knows how to delete the callable thing that's
  // stored in f_. Null if `f_` is trivially deletable.
  void (*delete_)(webrtc_function_impl::VoidUnion*);
};

}  // namespace webrtc

#endif  // RTC_BASE_UNTYPED_FUNCTION_H_
