carb/delegate/detail/DelegateBase.h
File members: carb/delegate/detail/DelegateBase.h
// Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include "../../Defines.h"
#include "../../Strong.h"
#include "../../container/IntrusiveList.h"
#include "../../thread/Util.h"
#include <memory>
#include <vector>
namespace carb
{
namespace delegate
{
template <class T>
class DelegateRef;
namespace detail
{
// The default executor class, which works in terms of thread IDs.
struct DefaultExec
{
using Id = carb::thread::ThreadId;
Id operator()() const
{
return carb::this_thread::getId();
}
};
template <class M, class E, class T>
class DelegateBase;
template <class Mutex, class Exec, class... Args>
class DelegateBase<Mutex, Exec, void(Args...)>
{
public:
using FunctionType = void(Args...);
CARB_STRONGTYPE(Handle, size_t);
CARB_DOC_CONSTEXPR static Handle kInvalidHandle{ 0 };
DelegateBase() = default;
DelegateBase(DelegateBase&& other);
DelegateBase& operator=(DelegateBase&& other);
~DelegateBase();
template <class Callable, class... BindArgs>
Handle Bind(Handle* hOut, Callable&& func, BindArgs&&... args);
template <class KeyType, class Callable, class... BindArgs>
void BindWithKey(KeyType&& key, Callable&& func, BindArgs&&... args);
template <class KeyType>
bool Unbind(KeyType&& key);
template <class KeyType>
bool HasKey(KeyType&& key) const noexcept;
bool UnbindCurrent();
void UnbindAll();
size_t Count() const noexcept;
bool HasPending() const noexcept;
bool IsEmpty() const noexcept;
template <class KeyType>
std::vector<std::decay_t<KeyType>> GetKeysByType() const;
void Call(Args... args);
void operator()(Args... args);
void swap(DelegateBase& other);
protected:
constexpr DelegateBase(std::nullptr_t);
DelegateBase(const DelegateBase& copy) : m_impl(copy.m_impl)
{
}
void copy(const DelegateBase& other)
{
m_impl = other.m_impl;
}
void reset()
{
m_impl.reset();
}
bool isValid() const noexcept
{
return m_impl != nullptr;
}
private:
using MutexType = Mutex;
using ExecType = Exec;
using ExecutorId = typename Exec::Id;
// Forward declaration of the base class for bindings.
struct BaseBinding;
// Forward declaration of the keyed bindings class.
template <class Key>
struct KeyedBinding;
// The container for storing bindings.
using Container = carb::container::IntrusiveList<BaseBinding, &BaseBinding::link>;
// Forward declaration of a call in progress.
struct ActiveCall;
// The container for storing active calls.
using ActiveCallList = carb::container::IntrusiveList<ActiveCall, &ActiveCall::link>;
// Forward declaration of our internal implementation.
struct Impl;
ActiveCall* lastCurrentThreadCall();
const ActiveCall* lastCurrentThreadCall() const;
void UnbindInternal(std::unique_lock<Mutex>& g, typename Container::iterator iter);
static size_t nextHandle();
std::shared_ptr<Impl> m_impl{ std::make_shared<Impl>() };
};
} // namespace detail
} // namespace delegate
} // namespace carb
#include "DelegateImpl.inl"