Extra2D/include/core/intrusive_ptr.h

173 lines
4.2 KiB
C
Raw Normal View History

#pragma once
#include <core/ref_counted.h>
#include <functional>
#include <utility>
namespace extra2d {
// ============================================================================
// 侵入式智能指针
// 参考 Cocos2d-x 的 IntrusivePtr 设计
// ============================================================================
template <class T>
class IntrusivePtr {
public:
using element_type = T;
// 默认构造函数
IntrusivePtr() : _ptr(nullptr) {}
// 从原始指针构造
IntrusivePtr(T* p) : _ptr(p) {
if (_ptr) {
_ptr->addRef();
}
}
// 拷贝构造函数
IntrusivePtr(const IntrusivePtr<T>& r) : _ptr(r._ptr) {
if (_ptr) {
_ptr->addRef();
}
}
// 从派生类拷贝构造
template <typename U>
IntrusivePtr(const IntrusivePtr<U>& r) : _ptr(r.get()) {
if (_ptr) {
_ptr->addRef();
}
}
// 移动构造函数
IntrusivePtr(IntrusivePtr<T>&& r) noexcept : _ptr(r.release()) {}
// 从派生类移动构造
template <typename U>
IntrusivePtr(IntrusivePtr<U>&& r) noexcept : _ptr(r.release()) {}
// 析构函数
~IntrusivePtr() {
if (_ptr) {
_ptr->release();
}
}
// 获取原始指针
T* get() const { return _ptr; }
// 解引用操作符
T& operator*() const { return *_ptr; }
// 箭头操作符
T* operator->() const { return _ptr; }
// 转换为原始指针(隐式转换)
operator T*() const { return _ptr; }
// 赋值操作符 - 原始指针
IntrusivePtr<T>& operator=(T* p) {
reset(p);
return *this;
}
// 赋值操作符 - 同类型
IntrusivePtr<T>& operator=(const IntrusivePtr<T>& r) {
return *this = r._ptr;
}
// 赋值操作符 - 派生类
template <typename U>
IntrusivePtr<T>& operator=(const IntrusivePtr<U>& r) {
return *this = r.get();
}
// 移动赋值
IntrusivePtr<T>& operator=(IntrusivePtr<T>&& r) noexcept {
IntrusivePtr<T>(std::move(r)).swap(*this);
return *this;
}
// 从派生类移动赋值
template <typename U>
IntrusivePtr<T>& operator=(IntrusivePtr<U>&& r) noexcept {
IntrusivePtr<T>(std::move(r)).swap(*this);
return *this;
}
// 比较操作符
bool operator==(std::nullptr_t) const { return _ptr == nullptr; }
bool operator==(T* r) const { return _ptr == r; }
bool operator!=(std::nullptr_t) const { return _ptr != nullptr; }
bool operator!=(T* r) const { return _ptr != r; }
bool operator<(const IntrusivePtr<T>& r) const { return _ptr < r._ptr; }
// 重置指针
void reset() noexcept {
if (_ptr) {
_ptr->release();
}
_ptr = nullptr;
}
void reset(T* p) {
// 先增加新指针的引用计数,再释放旧指针
// 这样可以处理自赋值的情况
if (p) {
p->addRef();
}
if (_ptr) {
_ptr->release();
}
_ptr = p;
}
// 交换指针
void swap(T** pp) noexcept {
T* p = _ptr;
_ptr = *pp;
*pp = p;
}
void swap(IntrusivePtr<T>& r) noexcept {
swap(&r._ptr);
}
// 释放指针所有权(不减少引用计数)
T* release() {
T* retVal = _ptr;
_ptr = nullptr;
return retVal;
}
private:
T* _ptr;
};
// ============================================================================
// 辅助函数
// ============================================================================
// 创建 IntrusivePtr 的便捷函数
template <typename T, typename... Args>
inline IntrusivePtr<T> makePtr(Args&&... args) {
return IntrusivePtr<T>(new T(std::forward<Args>(args)...));
}
} // namespace extra2d
// ============================================================================
// std::hash 特化
// ============================================================================
namespace std {
template <class T>
struct hash<extra2d::IntrusivePtr<T>> {
size_t operator()(const extra2d::IntrusivePtr<T>& val) const noexcept {
return hash<T*>{}(val.get());
}
};
} // namespace std