chromium/base/functional/callback_internal.h

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains utility functions and classes that help the
// implementation, and management of the Callback objects.

#ifndef BASE_FUNCTIONAL_CALLBACK_INTERNAL_H_
#define BASE_FUNCTIONAL_CALLBACK_INTERNAL_H_

#include <type_traits>
#include <utility>

#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/functional/callback_forward.h"
#include "base/memory/ref_counted.h"

namespace base {

struct FakeBindState;

namespace internal {

class BindStateBase;

template <bool is_method,
          bool is_nullable,
          bool is_callback,
          typename Functor,
          typename... BoundArgs>
struct BindState;

struct BASE_EXPORT BindStateBaseRefCountTraits {};

PassingType;

// BindStateBase is used to provide an opaque handle that the Callback
// class can use to represent a function object with bound arguments.  It
// behaves as an existential type that is used by a corresponding
// DoInvoke function to perform the function execution.  This allows
// us to shield the Callback class from the types of the bound argument via
// "type erasure."
// At the base level, the only task is to add reference counting data. Avoid
// using or inheriting any virtual functions. Creating a vtable for every
// BindState template instantiation results in a lot of bloat. Its only task is
// to call the destructor which can be done with a function pointer.
class BASE_EXPORT BindStateBase
    : public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {};

// Minimal wrapper around a `scoped_refptr<BindStateBase>`. It allows more
// expensive operations (such as ones that destroy `BindStateBase` or manipulate
// refcounts) to be defined out-of-line to reduce binary size.
class BASE_EXPORT TRIVIAL_ABI BindStateHolder {};

constexpr BindStateHolder::BindStateHolder() noexcept = default;

// TODO(dcheng): Try plumbing a scoped_refptr all the way through, since
// scoped_refptr is marked as TRIVIAL_ABI.
BindStateHolder::BindStateHolder(BindStateBase* bind_state)
    :{}

// Unlike the copy constructor, copy assignment operator, and move assignment
// operator, the move constructor is defaulted in the header because it
// generates minimal code: move construction does not change any refcounts, nor
// does it potentially destroy `BindStateBase`.
BindStateHolder::BindStateHolder(BindStateHolder&&) noexcept = default;

// Helpers for the `Then()` implementation.
template <typename OriginalCallback, typename ThenCallback>
struct ThenHelper;

// Specialization when original callback returns `void`.
ThenHelper<OriginalCallback<void (OriginalArgs...)>, ThenCallback<ThenR (ThenArgs...)>>;

// Specialization when original callback returns a non-void type.
ThenHelper<OriginalCallback<OriginalR (OriginalArgs...)>, ThenCallback<ThenR (ThenArgs...)>>;

}  // namespace internal
}  // namespace base

#endif  // BASE_FUNCTIONAL_CALLBACK_INTERNAL_H_