Files
UnrealEngine/Engine/Source/ThirdParty/Intel/ISPC/ispc-1.24.0/ispcrt/detail/IntrusivePtr.h
2025-05-18 13:04:45 +08:00

149 lines
4.0 KiB
C++

// Copyright 2020 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <atomic>
#include <iostream>
#include <stdexcept>
#include <type_traits>
namespace ispcrt {
class RefCounted {
public:
RefCounted() = default;
virtual ~RefCounted() = default;
RefCounted(const RefCounted &) = delete;
RefCounted(RefCounted &&) = delete;
RefCounted &operator=(const RefCounted &) = delete;
RefCounted &operator=(RefCounted &&) = delete;
void refInc() const;
void refDec() const;
long long useCount() const;
private:
mutable std::atomic<long long> refCounter{1};
};
// Inlined definitions //
inline void RefCounted::refInc() const { refCounter++; }
inline void RefCounted::refDec() const {
if ((--refCounter) == 0)
delete this;
}
inline long long RefCounted::useCount() const { return refCounter.load(); }
/////////////////////////////////////////////////////////////////////////////
// Pointer to a RefCounted object ///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
template <typename T> class IntrusivePtr {
static_assert(std::is_base_of<RefCounted, T>::value, "IntrusivePtr<T> can only be used with objects derived "
"from RefCounted");
public:
T *ptr{nullptr};
IntrusivePtr() = default;
~IntrusivePtr();
IntrusivePtr(const IntrusivePtr &input);
IntrusivePtr(IntrusivePtr &&input);
template <typename O> IntrusivePtr(const IntrusivePtr<O> &input);
IntrusivePtr(T *const input);
IntrusivePtr &operator=(const IntrusivePtr &input);
IntrusivePtr &operator=(IntrusivePtr &&input);
IntrusivePtr &operator=(T *input);
operator bool() const;
const T &operator*() const;
T &operator*();
const T *operator->() const;
T *operator->();
};
// Inlined definitions //
template <typename T> inline IntrusivePtr<T>::~IntrusivePtr() {
if (ptr)
ptr->refDec();
}
template <typename T> inline IntrusivePtr<T>::IntrusivePtr(const IntrusivePtr<T> &input) : ptr(input.ptr) {
if (ptr)
ptr->refInc();
}
template <typename T> inline IntrusivePtr<T>::IntrusivePtr(IntrusivePtr<T> &&input) : ptr(input.ptr) {
input.ptr = nullptr;
}
template <typename T>
template <typename O>
inline IntrusivePtr<T>::IntrusivePtr(const IntrusivePtr<O> &input) : ptr(input.ptr) {
if (ptr)
ptr->refInc();
}
template <typename T> inline IntrusivePtr<T>::IntrusivePtr(T *const input) : ptr(input) {
if (ptr)
ptr->refInc();
}
template <typename T> inline IntrusivePtr<T> &IntrusivePtr<T>::operator=(const IntrusivePtr &input) {
if (input.ptr)
input.ptr->refInc();
if (ptr)
ptr->refDec();
ptr = input.ptr;
return *this;
}
template <typename T> inline IntrusivePtr<T> &IntrusivePtr<T>::operator=(IntrusivePtr &&input) {
ptr = input.ptr;
input.ptr = nullptr;
return *this;
}
template <typename T> inline IntrusivePtr<T> &IntrusivePtr<T>::operator=(T *input) {
if (input)
input->refInc();
if (ptr)
ptr->refDec();
ptr = input;
return *this;
}
template <typename T> inline IntrusivePtr<T>::operator bool() const { return ptr != nullptr; }
template <typename T> inline const T &IntrusivePtr<T>::operator*() const { return *ptr; }
template <typename T> inline T &IntrusivePtr<T>::operator*() { return *ptr; }
template <typename T> inline const T *IntrusivePtr<T>::operator->() const { return ptr; }
template <typename T> inline T *IntrusivePtr<T>::operator->() { return ptr; }
// Inlined operators ////////////////////////////////////////////////////////
template <typename T> inline bool operator<(const IntrusivePtr<T> &a, const IntrusivePtr<T> &b) {
return a.ptr < b.ptr;
}
template <typename T> bool operator==(const IntrusivePtr<T> &a, const IntrusivePtr<T> &b) { return a.ptr == b.ptr; }
template <typename T> bool operator!=(const IntrusivePtr<T> &a, const IntrusivePtr<T> &b) { return a.ptr != b.ptr; }
} // namespace ispcrt