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_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();
|
||||||
@@ -28,7 +29,7 @@ public:
|
|||||||
void setMat4(const std::string& name, const glm::mat4& value);
|
void setMat4(const std::string& name, const glm::mat4& value);
|
||||||
void setTexture(const std::string& name, int slot);
|
void setTexture(const std::string& name, int slot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Shader(const std::string& name, uint32_t programID);
|
Shader(const std::string& name, uint32_t programID);
|
||||||
|
|
||||||
friend class ShaderManager;
|
friend class ShaderManager;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 的便捷函数
|
||||||
|
|||||||
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_.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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user