173 lines
4.2 KiB
C++
173 lines
4.2 KiB
C++
#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
|