refactor(base): 引入引用计数智能指针系统替换std::shared_ptr
- 新增RefObject基类实现引用计数功能 - 新增RefPtr智能指针模板类 - 修改Texture和Shader类继承自RefObject - 替换原有std::shared_ptr为RefPtr - 更新相关代码中的指针操作
This commit is contained in:
14
Frostbite2D/include/frostbite2D/base/Noncopyable.h
Normal file
14
Frostbite2D/include/frostbite2D/base/Noncopyable.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class Noncopyable {
|
||||
protected:
|
||||
Noncopyable() = default;
|
||||
|
||||
private:
|
||||
Noncopyable(const Noncopyable&) = delete;
|
||||
Noncopyable& operator=(const Noncopyable&) = delete;
|
||||
};
|
||||
|
||||
}
|
||||
24
Frostbite2D/include/frostbite2D/base/RefObject.h
Normal file
24
Frostbite2D/include/frostbite2D/base/RefObject.h
Normal 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_;
|
||||
};
|
||||
|
||||
}
|
||||
39
Frostbite2D/include/frostbite2D/base/RefPtr.h
Normal file
39
Frostbite2D/include/frostbite2D/base/RefPtr.h
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
4
Frostbite2D/include/frostbite2D/base/base.h
Normal file
4
Frostbite2D/include/frostbite2D/base/base.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/base/RefObject.h>
|
||||
#include <frostbite2D/base/RefPtr.h>
|
||||
178
Frostbite2D/include/frostbite2D/core/RefBasePtr.hpp
Normal file
178
Frostbite2D/include/frostbite2D/core/RefBasePtr.hpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#include <frostbite2D/base/RefObject.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class Shader {
|
||||
class Shader : public RefObject {
|
||||
public:
|
||||
Shader() = default;
|
||||
~Shader();
|
||||
@@ -28,7 +29,7 @@ public:
|
||||
void setMat4(const std::string& name, const glm::mat4& value);
|
||||
void setTexture(const std::string& name, int slot);
|
||||
|
||||
private:
|
||||
private:
|
||||
Shader(const std::string& name, uint32_t programID);
|
||||
|
||||
friend class ShaderManager;
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#include <frostbite2D/graphics/types.h>
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/base/RefObject.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
class Texture {
|
||||
class Texture : public RefObject {
|
||||
public:
|
||||
static Ptr<Texture> loadFromFile(const std::string& path);
|
||||
static Ptr<Texture> createFromMemory(uint8* data, int width, int height, int channels);
|
||||
@@ -29,9 +30,6 @@ public:
|
||||
private:
|
||||
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;
|
||||
int width_ = 0;
|
||||
int height_ = 0;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <frostbite2D/base/base.h>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -15,8 +17,8 @@ namespace frostbite2D {
|
||||
// ---------------------------------------------------------------------------
|
||||
// 智能指针别名
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T> using Ptr = std::shared_ptr<T>;
|
||||
template <typename T> using SharedPtr = std::shared_ptr<T>;
|
||||
template <typename T> using Ptr = RefPtr<T>;
|
||||
template <typename T> using SharedPtr = RefPtr<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 的便捷函数
|
||||
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>
|
||||
inline SharedPtr<T> makeShared(Args &&...args) {
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
return MakePtr<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// 创建 unique_ptr 的便捷函数
|
||||
|
||||
24
Frostbite2D/src/frostbite2D/base/RefObject.cpp
Normal file
24
Frostbite2D/src/frostbite2D/base/RefObject.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -73,7 +73,7 @@ void Batch::begin() {
|
||||
currentBatch_.indices.clear();
|
||||
currentBatch_.key = {0, 0, 0};
|
||||
currentBatch_.shader = nullptr;
|
||||
currentBatch_.texture.reset();
|
||||
currentBatch_.texture.Reset();
|
||||
}
|
||||
|
||||
void Batch::end() {
|
||||
@@ -169,12 +169,12 @@ void Batch::flushCurrentBatch() {
|
||||
|
||||
glDrawElements(GL_TRIANGLES,
|
||||
static_cast<GLsizei>(currentBatch_.indices.size()),
|
||||
GL_UNSIGNED_SHORT, 0);
|
||||
GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
currentBatch_.vertices.clear();
|
||||
currentBatch_.indices.clear();
|
||||
currentBatch_.shader = nullptr;
|
||||
currentBatch_.texture.reset();
|
||||
currentBatch_.texture.Reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ void ShaderManager::shutdown() {
|
||||
Shader* ShaderManager::getShader(const std::string& name) {
|
||||
auto it = shaders_.find(name);
|
||||
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());
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user