IObject.h#
Fully qualified name: carb/IObject.h
File members: carb/IObject.h
// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
//
// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
// property and proprietary rights in and to this material, related
// documentation and any modifications thereto. Any use, reproduction,
// disclosure or distribution of this material and related documentation
// without an express license agreement from NVIDIA CORPORATION or
// its affiliates is strictly prohibited.
#pragma once
#include "Interface.h"
#include "Assert.h"
#include <utility>
namespace carb
{
class IObject
{
public:
    CARB_PLUGIN_INTERFACE("carb::IObject", 1, 0)
    virtual ~IObject() = default;
    virtual size_t addRef() = 0;
    virtual size_t release() = 0;
};
enum class InitPolicy
{
    eBorrow,
    eSteal
};
template <class T>
class ObjectPtr
{
public:
    using InitPolicy = carb::InitPolicy;
    constexpr ObjectPtr() noexcept : m_object(nullptr)
    {
    }
    constexpr ObjectPtr(std::nullptr_t) noexcept : m_object(nullptr)
    {
    }
    explicit ObjectPtr(T* object) : m_object(object)
    {
        if (m_object)
        {
            m_object->addRef();
        }
    }
    ObjectPtr(T* object, InitPolicy policy) : m_object(object)
    {
        if (policy == InitPolicy::eBorrow && m_object != nullptr)
        {
            m_object->addRef();
        }
    }
    ObjectPtr(const ObjectPtr<T>& other) : ObjectPtr(other.m_object, InitPolicy::eBorrow)
    {
    }
    template <class U>
    ObjectPtr(const ObjectPtr<U>& other) : ObjectPtr(other.m_object, InitPolicy::eBorrow)
    {
    }
    constexpr ObjectPtr(ObjectPtr<T>&& other) noexcept : m_object(other.m_object)
    {
        other.m_object = nullptr;
    }
    template <class U>
    constexpr ObjectPtr(ObjectPtr<U>&& other) noexcept : m_object(other.m_object)
    {
        other.m_object = nullptr;
    }
    ~ObjectPtr()
    {
        _release();
    }
    constexpr T* get() const noexcept
    {
        return m_object;
    }
    constexpr T* operator->() const noexcept
    {
        CARB_ASSERT(m_object);
        return m_object;
    }
    constexpr T& operator*() const noexcept
    {
        CARB_ASSERT(m_object);
        return *m_object;
    }
    constexpr explicit operator bool() const noexcept
    {
        return get() != nullptr;
    }
    T* const* getAddressOf() const
    {
        return &m_object;
    }
    T** getAddressOf()
    {
        return &m_object;
    }
    T** releaseAndGetAddressOf()
    {
        _release();
        return &m_object;
    }
    T* detach()
    {
        T* temp = m_object;
        m_object = nullptr;
        return temp;
    }
    void attach(T* other)
    {
        _release();
        m_object = other;
    }
    ObjectPtr& operator=(std::nullptr_t)
    {
        _release();
        return *this;
    }
    ObjectPtr& operator=(T* other)
    {
        ObjectPtr(other).swap(*this);
        return *this;
    }
    template <typename U>
    ObjectPtr& operator=(U* other)
    {
        ObjectPtr(other).swap(*this);
        return *this;
    }
    ObjectPtr& operator=(const ObjectPtr& other)
    {
        ObjectPtr(other).swap(*this);
        return *this;
    }
    template <class U>
    ObjectPtr& operator=(const ObjectPtr<U>& other)
    {
        ObjectPtr(other).swap(*this);
        return *this;
    }
    ObjectPtr& operator=(ObjectPtr&& other)
    {
        other.swap(*this);
        return *this;
    }
    template <class U>
    ObjectPtr& operator=(ObjectPtr<U>&& other)
    {
        ObjectPtr(std::move(other)).swap(*this);
        return *this;
    }
    void swap(ObjectPtr& other)
    {
        std::swap(m_object, other.m_object);
    }
    [[nodiscard]] constexpr T* release() noexcept
    {
        return std::exchange(m_object, nullptr);
    }
    void reset(T* ptr = nullptr, InitPolicy policy = InitPolicy::eSteal)
    {
        ObjectPtr(ptr, policy).swap(*this);
    }
private:
    void _release()
    {
        if (T* old = std::exchange(m_object, nullptr))
        {
            old->release();
        }
    }
    T* m_object;
};
template <class T, class U>
bool operator==(const ObjectPtr<T>& lhs, const ObjectPtr<U>& rhs) noexcept
{
    return lhs.get() == rhs.get();
}
template <class T, class U>
bool operator==(const ObjectPtr<T>& lhs, const U* rhs) noexcept
{
    return lhs.get() == rhs;
}
template <class T, class U>
bool operator==(const T* lhs, const ObjectPtr<U>& rhs) noexcept
{
    return lhs == rhs.get();
}
template <class T>
bool operator==(const ObjectPtr<T>& lhs, std::nullptr_t) noexcept
{
    return lhs.get() == nullptr;
}
template <class T>
bool operator==(std::nullptr_t, const ObjectPtr<T>& rhs) noexcept
{
    return nullptr == rhs.get();
}
template <class T, class U>
bool operator!=(const ObjectPtr<T>& lhs, const ObjectPtr<U>& rhs) noexcept
{
    return lhs.get() != rhs.get();
}
template <class T, class U>
bool operator!=(const ObjectPtr<T>& lhs, const U* rhs) noexcept
{
    return lhs.get() != rhs;
}
template <class T, class U>
bool operator!=(const T* lhs, const ObjectPtr<U>& rhs) noexcept
{
    return lhs != rhs.get();
}
template <class T>
bool operator!=(const ObjectPtr<T>& lhs, std::nullptr_t) noexcept
{
    return lhs.get() != nullptr;
}
template <class T>
bool operator!=(std::nullptr_t, const ObjectPtr<T>& rhs) noexcept
{
    return nullptr != rhs.get();
}
template <class T>
inline ObjectPtr<T> stealObject(T* other)
{
    return ObjectPtr<T>(other, ObjectPtr<T>::InitPolicy::eSteal);
}
template <class T>
inline ObjectPtr<T> borrowObject(T* other)
{
    return ObjectPtr<T>(other, ObjectPtr<T>::InitPolicy::eBorrow);
}
} // namespace carb