refactor(base): 引入引用计数智能指针系统替换std::shared_ptr

- 新增RefObject基类实现引用计数功能
- 新增RefPtr智能指针模板类
- 修改Texture和Shader类继承自RefObject
- 替换原有std::shared_ptr为RefPtr
- 更新相关代码中的指针操作
This commit is contained in:
2026-03-17 04:50:15 +08:00
parent 092a28c30e
commit a09c344bb7
11 changed files with 298 additions and 14 deletions

View File

@@ -0,0 +1,14 @@
#pragma once
namespace frostbite2D {
class Noncopyable {
protected:
Noncopyable() = default;
private:
Noncopyable(const Noncopyable&) = delete;
Noncopyable& operator=(const Noncopyable&) = delete;
};
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <atomic>
#include <cstdint>
#include <frostbite2D/base/Noncopyable.h>
namespace frostbite2D {
class RefObject : protected Noncopyable {
public:
void Retain();
void Release();
uint32_t GetRefCount() const;
virtual ~RefObject();
protected:
RefObject();
private:
std::atomic<uint32_t> ref_count_;
};
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include <frostbite2D/base/RefObject.h>
#include <frostbite2D/core/RefBasePtr.hpp>
namespace frostbite2D {
struct DefaultRefPtrPolicy {
void Retain(RefObject* ptr) {
if (ptr) {
ptr->Retain();
}
}
void Release(RefObject* ptr) {
if (ptr) {
ptr->Release();
}
}
};
template <typename T>
using RefPtr = RefBasePtr<T, DefaultRefPtrPolicy>;
template <typename T, typename... Args>
RefPtr<T> MakePtr(Args&&... args) {
static_assert(std::is_base_of<RefObject, T>::value,
"T must be derived from RefObject");
return RefPtr<T>(new T(std::forward<Args>(args)...));
}
template <typename T>
RefPtr<T> MakePtr(T* ptr) {
static_assert(std::is_base_of<RefObject, T>::value,
"T must be derived from RefObject");
return RefPtr<T>(ptr);
}
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include <frostbite2D/base/RefObject.h>
#include <frostbite2D/base/RefPtr.h>

View File

@@ -0,0 +1,178 @@
#pragma once
#include <utility>
#include <type_traits>
namespace frostbite2D {
template <typename T, typename RefPolicy>
class RefBasePtr : protected RefPolicy {
public:
using value_type = T;
using pointer_type = T*;
using const_pointer_type = const T*;
using reference_type = T&;
using const_reference_type = const T&;
RefBasePtr() noexcept : ptr_(nullptr) {}
RefBasePtr(std::nullptr_t) noexcept : ptr_(nullptr) {}
RefBasePtr(pointer_type p) : ptr_(p) {
RefPolicy::Retain(ptr_);
}
RefBasePtr(const RefBasePtr& other) : ptr_(other.ptr_) {
RefPolicy::Retain(ptr_);
}
RefBasePtr(RefBasePtr&& other) noexcept : ptr_(nullptr) {
Swap(other);
}
~RefBasePtr() {
Tidy();
}
template <typename U,
typename std::enable_if<std::is_convertible<U*, T*>::value, int>::type = 0>
RefBasePtr(const RefBasePtr<U, RefPolicy>& other) {
ptr_ = dynamic_cast<pointer_type>(other.Get());
RefPolicy::Retain(ptr_);
}
pointer_type Get() const noexcept { return ptr_; }
pointer_type* GetAddressOfAndRelease() {
Tidy();
return &ptr_;
}
void Reset(pointer_type ptr = nullptr) {
if (ptr) {
RefBasePtr(ptr).Swap(*this);
} else {
Tidy();
}
}
void Swap(RefBasePtr& other) noexcept {
std::swap(ptr_, other.ptr_);
}
pointer_type operator->() { return ptr_; }
const_pointer_type operator->() const { return ptr_; }
reference_type operator*() { return *ptr_; }
const_reference_type operator*() const { return *ptr_; }
pointer_type* operator&() { return this->GetAddressOfAndRelease(); }
operator bool() const noexcept { return ptr_ != nullptr; }
bool operator!() const noexcept { return ptr_ == nullptr; }
RefBasePtr& operator=(const RefBasePtr& other) {
if (other.ptr_ != ptr_) {
RefBasePtr(other).Swap(*this);
}
return *this;
}
RefBasePtr& operator=(RefBasePtr&& other) noexcept {
if (other.ptr_ != ptr_) {
other.Swap(*this);
}
return *this;
}
RefBasePtr& operator=(pointer_type p) {
if (p != ptr_) {
RefBasePtr(p).Swap(*this);
}
return *this;
}
template <typename U,
typename std::enable_if<std::is_convertible<U*, T*>::value, int>::type = 0>
RefBasePtr& operator=(const RefBasePtr<U, RefPolicy>& other) {
if (other.Get() != ptr_) {
RefBasePtr(dynamic_cast<pointer_type>(other.Get())).Swap(*this);
}
return *this;
}
RefBasePtr& operator=(std::nullptr_t) {
Tidy();
return *this;
}
private:
void Tidy() {
RefPolicy::Release(ptr_);
ptr_ = nullptr;
}
pointer_type ptr_;
};
template <class T, class U, class RefPolicy>
bool operator==(const RefBasePtr<T, RefPolicy>& lhs,
const RefBasePtr<U, RefPolicy>& rhs) noexcept {
return lhs.Get() == rhs.Get();
}
template <class T, class RefPolicy>
bool operator==(const RefBasePtr<T, RefPolicy>& lhs, T* rhs) noexcept {
return lhs.Get() == rhs;
}
template <class T, class RefPolicy>
bool operator==(T* lhs, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
return lhs == rhs.Get();
}
template <class T, class RefPolicy>
bool operator==(const RefBasePtr<T, RefPolicy>& lhs, std::nullptr_t) noexcept {
return !static_cast<bool>(lhs);
}
template <class T, class RefPolicy>
bool operator==(std::nullptr_t, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
return !static_cast<bool>(rhs);
}
template <class T, class U, class RefPolicy>
bool operator!=(const RefBasePtr<T, RefPolicy>& lhs,
const RefBasePtr<U, RefPolicy>& rhs) noexcept {
return !(lhs == rhs);
}
template <class T, class RefPolicy>
bool operator!=(const RefBasePtr<T, RefPolicy>& lhs, T* rhs) noexcept {
return lhs.Get() != rhs;
}
template <class T, class RefPolicy>
bool operator!=(T* lhs, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
return lhs != rhs.Get();
}
template <class T, class RefPolicy>
bool operator!=(const RefBasePtr<T, RefPolicy>& lhs, std::nullptr_t) noexcept {
return static_cast<bool>(lhs);
}
template <class T, class RefPolicy>
bool operator!=(std::nullptr_t, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
return static_cast<bool>(rhs);
}
template <class T, class U, class RefPolicy>
bool operator<(const RefBasePtr<T, RefPolicy>& lhs,
const RefBasePtr<U, RefPolicy>& rhs) noexcept {
return lhs.Get() < rhs.Get();
}
template <class T, class RefPolicy>
void swap(RefBasePtr<T, RefPolicy>& lhs, RefBasePtr<T, RefPolicy>& rhs) noexcept {
lhs.Swap(rhs);
}
}

View File

@@ -2,12 +2,13 @@
#include <frostbite2D/types/type_alias.h> #include <frostbite2D/types/type_alias.h>
#include <frostbite2D/types/type_math.h> #include <frostbite2D/types/type_math.h>
#include <frostbite2D/base/RefObject.h>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
namespace frostbite2D { namespace frostbite2D {
class Shader { class Shader : public RefObject {
public: public:
Shader() = default; Shader() = default;
~Shader(); ~Shader();

View File

@@ -2,12 +2,13 @@
#include <frostbite2D/graphics/types.h> #include <frostbite2D/graphics/types.h>
#include <frostbite2D/types/type_alias.h> #include <frostbite2D/types/type_alias.h>
#include <frostbite2D/base/RefObject.h>
#include <string> #include <string>
#include <memory> #include <memory>
namespace frostbite2D { namespace frostbite2D {
class Texture { class Texture : public RefObject {
public: public:
static Ptr<Texture> loadFromFile(const std::string& path); static Ptr<Texture> loadFromFile(const std::string& path);
static Ptr<Texture> createFromMemory(uint8* data, int width, int height, int channels); static Ptr<Texture> createFromMemory(uint8* data, int width, int height, int channels);
@@ -29,9 +30,6 @@ public:
private: private:
Texture(int width, int height, uint32_t id); Texture(int width, int height, uint32_t id);
friend class std::shared_ptr<Texture>;
template<typename T, typename... Args> friend Ptr<T> makePtr(Args &&...args);
uint32_t textureID_ = 0; uint32_t textureID_ = 0;
int width_ = 0; int width_ = 0;
int height_ = 0; int height_ = 0;

View File

@@ -4,6 +4,8 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <frostbite2D/base/base.h>
namespace frostbite2D { namespace frostbite2D {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -15,8 +17,8 @@ namespace frostbite2D {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// 智能指针别名 // 智能指针别名
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename T> using Ptr = std::shared_ptr<T>; template <typename T> using Ptr = RefPtr<T>;
template <typename T> using SharedPtr = std::shared_ptr<T>; template <typename T> using SharedPtr = RefPtr<T>;
template <typename T> using UniquePtr = std::unique_ptr<T>; template <typename T> using UniquePtr = std::unique_ptr<T>;
@@ -24,12 +26,12 @@ template <typename T> using WeakPtr = std::weak_ptr<T>;
/// 创建 shared_ptr 的便捷函数 /// 创建 shared_ptr 的便捷函数
template <typename T, typename... Args> inline Ptr<T> makePtr(Args &&...args) { template <typename T, typename... Args> inline Ptr<T> makePtr(Args &&...args) {
return std::make_shared<T>(std::forward<Args>(args)...); return MakePtr<T>(std::forward<Args>(args)...);
} }
template <typename T, typename... Args> template <typename T, typename... Args>
inline SharedPtr<T> makeShared(Args &&...args) { inline SharedPtr<T> makeShared(Args &&...args) {
return std::make_shared<T>(std::forward<Args>(args)...); return MakePtr<T>(std::forward<Args>(args)...);
} }
/// 创建 unique_ptr 的便捷函数 /// 创建 unique_ptr 的便捷函数

View File

@@ -0,0 +1,24 @@
#include <frostbite2D/base/RefObject.h>
namespace frostbite2D {
RefObject::RefObject() : ref_count_(0) {}
RefObject::~RefObject() {}
void RefObject::Retain() {
++ref_count_;
}
void RefObject::Release() {
--ref_count_;
if (ref_count_ == 0) {
delete this;
}
}
uint32_t RefObject::GetRefCount() const {
return ref_count_.load();
}
}

View File

@@ -73,7 +73,7 @@ void Batch::begin() {
currentBatch_.indices.clear(); currentBatch_.indices.clear();
currentBatch_.key = {0, 0, 0}; currentBatch_.key = {0, 0, 0};
currentBatch_.shader = nullptr; currentBatch_.shader = nullptr;
currentBatch_.texture.reset(); currentBatch_.texture.Reset();
} }
void Batch::end() { void Batch::end() {
@@ -174,7 +174,7 @@ void Batch::flushCurrentBatch() {
currentBatch_.vertices.clear(); currentBatch_.vertices.clear();
currentBatch_.indices.clear(); currentBatch_.indices.clear();
currentBatch_.shader = nullptr; currentBatch_.shader = nullptr;
currentBatch_.texture.reset(); currentBatch_.texture.Reset();
} }
} }

View File

@@ -38,7 +38,7 @@ void ShaderManager::shutdown() {
Shader* ShaderManager::getShader(const std::string& name) { Shader* ShaderManager::getShader(const std::string& name) {
auto it = shaders_.find(name); auto it = shaders_.find(name);
if (it != shaders_.end()) { if (it != shaders_.end()) {
return it->second.get(); return it->second.Get();
} }
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Shader not found: %s", name.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Shader not found: %s", name.c_str());
return nullptr; return nullptr;