carb/IObject.h
File members: carb/IObject.h
// Copyright (c) 2020-2022, 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 "Interface.h"
#include <cstdint>
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;
};
template <class T>
class ObjectPtr
{
public:
enum class InitPolicy
{
eBorrow,
eSteal
};
ObjectPtr() : m_object(nullptr)
{
}
ObjectPtr(std::nullptr_t) : 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)
{
}
ObjectPtr(ObjectPtr<T>&& other) : m_object(other.m_object)
{
other.m_object = nullptr;
}
template <class U>
ObjectPtr(ObjectPtr<U>&& other) : m_object(other.m_object)
{
other.m_object = nullptr;
}
~ObjectPtr()
{
_release();
}
T* get() const
{
return m_object;
}
T* operator->() const
{
CARB_ASSERT(m_object);
return m_object;
}
T& operator*() const
{
CARB_ASSERT(m_object);
return *m_object;
}
explicit operator bool() const
{
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=(decltype(nullptr))
{
_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;
}
template <class U>
bool operator==(const ObjectPtr<U>& other) const
{
return get() == other.get();
}
template <class U>
bool operator!=(const ObjectPtr<U>& other) const
{
return get() != other.get();
}
void swap(ObjectPtr& other)
{
std::swap(m_object, other.m_object);
}
private:
void _release()
{
if (T* old = std::exchange(m_object, nullptr))
{
old->release();
}
}
T* m_object;
};
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