diff --git a/include/bedrock/core/memory.h b/include/bedrock/core/memory.h index 6f484a4e5..bacf63bf5 100644 --- a/include/bedrock/core/memory.h +++ b/include/bedrock/core/memory.h @@ -21,21 +21,111 @@ class OwnerPtr; template struct SharedCounter { - T *ptr; - std::atomic share_count; - std::atomic weak_count; + T *ptr{nullptr}; + std::atomic share_count{1}; + std::atomic weak_count{0}; }; template class SharedPtr { public: - SharedCounter *pc; + constexpr SharedPtr() noexcept = default; + constexpr SharedPtr(nullptr_t) noexcept {} // NOLINT(*-explicit-constructor) + explicit SharedPtr(T *ptr) + { + if (ptr) { + pc_ = new SharedCounter(); + pc_->ptr = ptr; + } + } + + ~SharedPtr() noexcept + { + if (pc_) { + if (--pc_->share_count <= 0) { + delete pc_->ptr; + pc_->ptr = nullptr; + + if (pc_->weak_count <= 0) { + delete pc_; + } + } + } + } + + // copy constructor + SharedPtr(const SharedPtr &other) noexcept + { + if (other.pc_) { + other.pc_->share_count++; + } + pc_ = other.pc_; + } + + // move constructor + SharedPtr(SharedPtr &&other) noexcept + { + pc_ = other.pc_; + other.pc_ = nullptr; + } + + // copy assignment operator + SharedPtr &operator=(const SharedPtr &other) noexcept + { + SharedPtr(other).swap(*this); + return *this; + } + + // move assignment operator + SharedPtr &operator=(SharedPtr &&other) noexcept + { + SharedPtr(std::move(other)).swap(*this); + return *this; + } + + void reset() noexcept + { + SharedPtr().swap(*this); + } + + void reset(T *ptr) noexcept + { + SharedPtr(ptr).swap(*this); + } + + T *operator->() const noexcept + { + return get(); + } + + T &operator*() const noexcept + { + return *get(); + } + + explicit operator bool() const + { + return get() != nullptr; + } + +private: + void swap(SharedPtr &other) noexcept + { + std::swap(pc_, other.pc_); + } + + T *get() const noexcept + { + return pc_ ? pc_->ptr : nullptr; + } + + SharedCounter *pc_{nullptr}; }; template class WeakPtr { -public: - SharedCounter *pc; +private: + SharedCounter *pc_; }; template