Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // #pragma once
- #include "sw_fwd.h" // Forward declaration
- #include <cstddef> // std::nullptr_t
- #include <array>
- #include <concepts>
- #include <utility>
- // https://en.cppreference.com/w/cpp/memory/shared_ptr
- struct ControlBlockBase {
- size_t strong_counter_, weak_counter_;
- ControlBlockBase() : strong_counter_(1), weak_counter_ (0) {}
- virtual void ObjClear() {}
- virtual void WeakCounterDec() {}
- virtual void StrongCounterDec() {}
- void WeakCounterInc() {
- ++weak_counter_;
- }
- void StrongCounterInc() {
- ++strong_counter_;
- }
- };
- template<typename T, typename Y>
- concept CanCreatedFrom = (std::convertible_to<T, Y> || std::same_as<T, Y> || std::derived_from<Y, T>);
- template <typename T>
- class SharedPtr {
- private:
- struct ControlBlockPtr : public ControlBlockBase {
- T* ptr_;
- ControlBlockPtr(std::nullptr_t) : ControlBlockBase(), ptr_(nullptr) {}
- ControlBlockPtr(T* ptr) : ControlBlockBase(), ptr_(ptr) {}
- void WeakCounterDec() override {
- --(this->weak_counter_);
- if (!this->weak_counter_ && !this->strong_counter_) {
- delete this;
- }
- }
- void StrongCounterDec() override {
- --this->strong_counter_;
- if (!this->strong_counter_) {
- ObjClear();
- if (!this->weak_counter_) {
- delete this;
- }
- }
- }
- void ObjClear() override {
- if (ptr_) {
- delete ptr_;
- }
- }
- T* Get() const {
- return ptr_;
- }
- T* Get() {
- return ptr_;
- }
- };
- struct ControlBlockObj : public ControlBlockBase {
- alignas(T) std::array<char, sizeof(T)> data;
- T* Get() const {
- return reinterpret_cast<T*>(const_cast<char*>(data.data()));;
- }
- T* Get() {
- return reinterpret_cast<T*>(const_cast<char*>(data.data()));;
- }
- ControlBlockObj(std::nullptr_t) : ControlBlockBase() {
- new (Get()) T();
- }
- template<typename... Args>
- ControlBlockObj(Args&&... args) : ControlBlockBase() {
- new (Get()) T(std::forward<Args>(args)...);
- }
- void ObjClear() override {
- if (Get()) {
- Get()->~T();
- }
- }
- void WeakCounterDec() override {
- --this->weak_counter_;
- if (!this->weak_counter_ && !this->strong_counter_) {
- delete this;
- }
- }
- void StrongCounterDec() override {
- --this->strong_counter_;
- if (!this->strong_counter_) {
- ObjClear();
- if (!this->weak_counter_) {
- delete this;
- }
- }
- }
- };
- T *ptr_;
- ControlBlockBase *cb_;
- void CbCheck() {
- if (!cb_) cb_ = new ControlBlockPtr(nullptr);
- }
- public:
- void Zeroize() {
- cb_ = nullptr;
- ptr_ = nullptr;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- // Constructors
- SharedPtr() : cb_(nullptr), ptr_(nullptr) {}
- SharedPtr(std::nullptr_t) : cb_(nullptr), ptr_(nullptr) {}
- template<typename Y>
- requires (CanCreatedFrom<T, Y>)
- SharedPtr(Y* ptr) : ptr_(reinterpret_cast<T*>(ptr)) {
- cb_ = new ControlBlockPtr(reinterpret_cast<T*>(ptr));
- }
- template<typename Y>
- requires (CanCreatedFrom<T, Y>)
- SharedPtr(const SharedPtr<Y>& other) {
- cb_ = other.GetControlBlock();
- ptr_ = reinterpret_cast<T*>(other.Get());
- if (cb_) {
- cb_->StrongCounterInc();
- }
- }
- SharedPtr(const SharedPtr& other) {
- if (&other == this) {
- return;
- }
- cb_ = other.GetControlBlock();
- ptr_ = other.Get();
- if (cb_) {
- cb_->StrongCounterInc();
- }
- }
- template<typename Y>
- requires (CanCreatedFrom<T, Y>)
- SharedPtr(SharedPtr<Y>&& other) {
- Reset();
- std::swap(cb_, other.GetControlBlock());
- ptr_ = other.Get();
- other.Zeroize();
- }
- SharedPtr(ControlBlockObj *cb) : cb_(cb), ptr_(cb->Get()) {}
- // Aliasing constructor
- // #8 from https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
- template <typename Y>
- SharedPtr(const SharedPtr<Y>& other, T* ptr) {
- Reset();
- cb_ = other.GetControlBlock();
- if (cb_) {
- cb_->StrongCounterInc();
- }
- ptr_ = ptr;
- }
- // Promote `WeakPtr`
- // #11 from https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
- explicit SharedPtr(const WeakPtr<T>& other);
- ////////////////////////////////////////////////////////////////////////////////////////////////
- // `operator=`-s
- template<typename Y>
- requires (CanCreatedFrom<T, Y>)
- SharedPtr& operator=(SharedPtr<Y>&& other) {
- Reset();
- std::swap(cb_, other.GetControlBlock());
- ptr_ = other.Get();
- other.Zeroize();
- return *this;
- }
- template<typename Y>
- requires (CanCreatedFrom<T, Y>)
- SharedPtr& operator=(const SharedPtr<Y>& other) {
- Reset();
- cb_ = other.GetControlBlock();
- ptr_ = reinterpret_cast<T*>(other.Get());
- if (cb_) {
- cb_->StrongCounterInc();
- }
- return *this;
- }
- SharedPtr& operator=(const SharedPtr& other) {
- if (&other == this) {
- return *this;
- }
- Reset();
- cb_ = other.GetControlBlock();
- ptr_ = reinterpret_cast<T*>(other.Get());
- if (cb_) {
- cb_->StrongCounterInc();
- }
- return *this;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- // Destructor
- ~SharedPtr() {
- Reset();
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- // Modifiers
- void Reset() {
- if (cb_ ) {
- cb_->StrongCounterDec();
- }
- Zeroize();
- }
- void Reset(T* ptr) {
- Reset();
- cb_ = new ControlBlockPtr(ptr);
- ptr_ = ptr;
- }
- template<typename Y>
- requires (CanCreatedFrom<T, Y>)
- void Swap(SharedPtr<Y>& other) {
- std::swap(cb_, other.GetControlBlock());
- std::swap(ptr_, other.Get());
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- // Observers
- T* Get() const {
- return ptr_;
- }
- T*& Get() {
- return ptr_;
- }
- T& operator*() const {
- return *ptr_;
- }
- T* operator->() const {
- return ptr_;
- }
- size_t UseCount() const {
- if (cb_) {
- return cb_->strong_counter_;
- } else {
- return 0;
- }
- }
- explicit operator bool() const {
- return ptr_ != nullptr;
- }
- ControlBlockBase* GetControlBlock() const {
- return cb_;
- }
- ControlBlockBase*& GetControlBlock() {
- return cb_;
- }
- template <typename U, typename... Args>
- friend SharedPtr<U> MakeShared(Args&&... args);
- };
- template <typename T, typename U>
- inline bool operator==(const SharedPtr<T>& left, const SharedPtr<U>& right) {
- return left.cb_ == right.cb_;
- }
- // Allocate memory only once
- template <typename T, typename... Args>
- SharedPtr<T> MakeShared(Args&&... args) {
- return SharedPtr<T>(new typename SharedPtr<T>::ControlBlockObj(std::forward<Args>(args)...));
- }
- // Look for usage examples in tests
- template <typename T>
- class EnableSharedFromThis {
- public:
- SharedPtr<T> SharedFromThis();
- SharedPtr<const T> SharedFromThis() const;
- WeakPtr<T> WeakFromThis() noexcept;
- WeakPtr<const T> WeakFromThis() const noexcept;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement