Advertisement
Ilya_konstantinov

Untitled

Oct 10th, 2024
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.09 KB | None | 0 0
  1. // #pragma once
  2.  
  3. #include "sw_fwd.h"  // Forward declaration
  4.  
  5. #include <cstddef>  // std::nullptr_t
  6. #include <array>
  7. #include <concepts>
  8. #include <utility>
  9. // https://en.cppreference.com/w/cpp/memory/shared_ptr
  10.  
  11. struct ControlBlockBase {
  12.     size_t strong_counter_, weak_counter_;
  13.     ControlBlockBase() : strong_counter_(1), weak_counter_ (0) {}
  14.     virtual void ObjClear() {}
  15.     virtual void WeakCounterDec() {}
  16.     virtual void StrongCounterDec() {}
  17.  
  18.     void WeakCounterInc() {
  19.         ++weak_counter_;
  20.     }
  21.    
  22.     void StrongCounterInc() {
  23.         ++strong_counter_;
  24.     }
  25. };
  26.  
  27. template<typename T, typename Y>
  28. concept CanCreatedFrom = (std::convertible_to<T, Y> || std::same_as<T, Y> || std::derived_from<Y, T>);
  29.  
  30. template <typename T>
  31. class SharedPtr {
  32. private:    
  33.     struct ControlBlockPtr : public ControlBlockBase {
  34.         T* ptr_;
  35.  
  36.         ControlBlockPtr(std::nullptr_t) : ControlBlockBase(), ptr_(nullptr) {}
  37.         ControlBlockPtr(T* ptr) : ControlBlockBase(), ptr_(ptr) {}
  38.  
  39.         void WeakCounterDec() override {
  40.             --(this->weak_counter_);
  41.             if (!this->weak_counter_ && !this->strong_counter_) {
  42.                 delete this;
  43.             }
  44.         }
  45.  
  46.         void StrongCounterDec() override {
  47.             --this->strong_counter_;
  48.             if (!this->strong_counter_) {
  49.                 ObjClear();
  50.                 if (!this->weak_counter_) {
  51.                     delete this;
  52.                 }
  53.             }
  54.         }
  55.  
  56.         void ObjClear() override {
  57.             if (ptr_) {
  58.                 delete ptr_;
  59.             }
  60.         }
  61.  
  62.         T* Get() const {
  63.             return ptr_;
  64.         }
  65.  
  66.         T* Get() {
  67.             return ptr_;
  68.         }
  69.     };
  70.  
  71.     struct ControlBlockObj : public ControlBlockBase {
  72.         alignas(T) std::array<char, sizeof(T)> data;
  73.  
  74.         T* Get() const {
  75.             return reinterpret_cast<T*>(const_cast<char*>(data.data()));;
  76.         }
  77.  
  78.         T* Get() {
  79.             return reinterpret_cast<T*>(const_cast<char*>(data.data()));;
  80.         }
  81.        
  82.         ControlBlockObj(std::nullptr_t) : ControlBlockBase() {
  83.             new (Get()) T();
  84.         }
  85.    
  86.         template<typename... Args>
  87.         ControlBlockObj(Args&&... args) : ControlBlockBase() {
  88.             new (Get()) T(std::forward<Args>(args)...);
  89.         }
  90.  
  91.         void ObjClear() override {
  92.             if (Get()) {
  93.                 Get()->~T();
  94.             }
  95.         }
  96.  
  97.         void WeakCounterDec() override {
  98.             --this->weak_counter_;
  99.             if (!this->weak_counter_ && !this->strong_counter_) {
  100.                 delete this;
  101.             }
  102.         }
  103.  
  104.         void StrongCounterDec() override {
  105.             --this->strong_counter_;
  106.             if (!this->strong_counter_) {
  107.                 ObjClear();
  108.                 if (!this->weak_counter_) {
  109.                     delete this;
  110.                 }
  111.             }
  112.         }
  113.     };
  114.  
  115.     T *ptr_;
  116.     ControlBlockBase *cb_;
  117.  
  118.     void CbCheck() {
  119.         if (!cb_) cb_ = new ControlBlockPtr(nullptr);
  120.     }
  121.  
  122. public:
  123.  
  124.     void Zeroize() {
  125.         cb_ = nullptr;
  126.         ptr_ = nullptr;
  127.     }
  128.  
  129.     ////////////////////////////////////////////////////////////////////////////////////////////////
  130.     // Constructors
  131.  
  132.     SharedPtr() : cb_(nullptr), ptr_(nullptr) {}
  133.    
  134.     SharedPtr(std::nullptr_t) : cb_(nullptr), ptr_(nullptr) {}
  135.  
  136.     template<typename Y>
  137.     requires (CanCreatedFrom<T, Y>)
  138.     SharedPtr(Y* ptr) : ptr_(reinterpret_cast<T*>(ptr)) {
  139.         cb_ = new ControlBlockPtr(reinterpret_cast<T*>(ptr));
  140.     }
  141.  
  142.     template<typename Y>
  143.     requires (CanCreatedFrom<T, Y>)
  144.     SharedPtr(const SharedPtr<Y>& other) {
  145.         cb_ = other.GetControlBlock();
  146.         ptr_ = reinterpret_cast<T*>(other.Get());
  147.         if (cb_) {
  148.             cb_->StrongCounterInc();
  149.         }
  150.     }
  151.  
  152.  
  153.     SharedPtr(const SharedPtr& other) {
  154.         if (&other == this) {
  155.             return;
  156.         }
  157.         cb_ = other.GetControlBlock();
  158.         ptr_ = other.Get();
  159.         if (cb_) {
  160.             cb_->StrongCounterInc();
  161.         }
  162.     }
  163.  
  164.     template<typename Y>
  165.     requires (CanCreatedFrom<T, Y>)
  166.     SharedPtr(SharedPtr<Y>&& other)  {
  167.         Reset();
  168.         std::swap(cb_, other.GetControlBlock());
  169.         ptr_ = other.Get();
  170.         other.Zeroize();
  171.     }
  172.  
  173.     SharedPtr(ControlBlockObj *cb) : cb_(cb), ptr_(cb->Get()) {}
  174.  
  175.     // Aliasing constructor
  176.     // #8 from https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
  177.     template <typename Y>
  178.     SharedPtr(const SharedPtr<Y>& other, T* ptr) {
  179.         Reset();
  180.         cb_ = other.GetControlBlock();
  181.         if (cb_) {
  182.             cb_->StrongCounterInc();
  183.         }
  184.         ptr_ = ptr;
  185.     }
  186.  
  187.     // Promote `WeakPtr`
  188.     // #11 from https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
  189.     explicit SharedPtr(const WeakPtr<T>& other);
  190.  
  191.     ////////////////////////////////////////////////////////////////////////////////////////////////
  192.     // `operator=`-s
  193.    
  194.     template<typename Y>
  195.     requires (CanCreatedFrom<T, Y>)
  196.     SharedPtr& operator=(SharedPtr<Y>&& other) {
  197.         Reset();
  198.         std::swap(cb_, other.GetControlBlock());
  199.         ptr_ = other.Get();
  200.         other.Zeroize();
  201.         return *this;
  202.     }
  203.  
  204.     template<typename Y>
  205.     requires (CanCreatedFrom<T, Y>)
  206.     SharedPtr& operator=(const SharedPtr<Y>& other) {
  207.         Reset();
  208.         cb_ = other.GetControlBlock();
  209.         ptr_ = reinterpret_cast<T*>(other.Get());
  210.         if (cb_) {
  211.             cb_->StrongCounterInc();
  212.         }
  213.         return *this;
  214.     }
  215.  
  216.     SharedPtr& operator=(const SharedPtr& other) {
  217.         if (&other == this) {
  218.             return *this;
  219.         }
  220.         Reset();
  221.         cb_ = other.GetControlBlock();
  222.         ptr_ = reinterpret_cast<T*>(other.Get());
  223.         if (cb_) {
  224.             cb_->StrongCounterInc();
  225.         }
  226.         return *this;
  227.     }
  228.  
  229.  
  230.     ////////////////////////////////////////////////////////////////////////////////////////////////
  231.     // Destructor
  232.  
  233.     ~SharedPtr() {
  234.         Reset();
  235.     }
  236.  
  237.     ////////////////////////////////////////////////////////////////////////////////////////////////
  238.     // Modifiers
  239.  
  240.     void Reset() {
  241.         if (cb_ ) {
  242.             cb_->StrongCounterDec();
  243.         }
  244.         Zeroize();
  245.     }
  246.    
  247.     void Reset(T* ptr) {
  248.         Reset();
  249.         cb_ = new ControlBlockPtr(ptr);
  250.         ptr_ = ptr;
  251.     }
  252.  
  253.  
  254.     template<typename Y>
  255.     requires (CanCreatedFrom<T, Y>)
  256.     void Swap(SharedPtr<Y>& other) {
  257.         std::swap(cb_, other.GetControlBlock());
  258.         std::swap(ptr_, other.Get());
  259.     }
  260.  
  261.     ////////////////////////////////////////////////////////////////////////////////////////////////
  262.     // Observers
  263.  
  264.     T* Get() const {
  265.         return ptr_;
  266.     }
  267.  
  268.     T*& Get() {
  269.         return ptr_;
  270.     }
  271.  
  272.     T& operator*() const {
  273.         return *ptr_;
  274.     }
  275.  
  276.     T* operator->() const {
  277.         return ptr_;
  278.     }
  279.  
  280.     size_t UseCount() const {
  281.         if (cb_) {
  282.             return cb_->strong_counter_;
  283.         } else {
  284.             return 0;
  285.         }
  286.     }
  287.  
  288.     explicit operator bool() const {
  289.         return ptr_ != nullptr;
  290.     }
  291.  
  292.     ControlBlockBase* GetControlBlock() const {
  293.         return cb_;
  294.     }
  295.  
  296.     ControlBlockBase*& GetControlBlock() {
  297.         return cb_;
  298.     }
  299.  
  300.     template <typename U, typename... Args>
  301.     friend SharedPtr<U> MakeShared(Args&&... args);
  302. };
  303.  
  304. template <typename T, typename U>
  305. inline bool operator==(const SharedPtr<T>& left, const SharedPtr<U>& right) {
  306.     return left.cb_ == right.cb_;
  307. }
  308.  
  309. // Allocate memory only once
  310. template <typename T, typename... Args>
  311. SharedPtr<T> MakeShared(Args&&... args) {
  312.     return SharedPtr<T>(new typename SharedPtr<T>::ControlBlockObj(std::forward<Args>(args)...));
  313. }
  314.  
  315. // Look for usage examples in tests
  316. template <typename T>
  317. class EnableSharedFromThis {
  318. public:
  319.     SharedPtr<T> SharedFromThis();
  320.     SharedPtr<const T> SharedFromThis() const;
  321.  
  322.     WeakPtr<T> WeakFromThis() noexcept;
  323.     WeakPtr<const T> WeakFromThis() const noexcept;
  324. };
  325.  
  326.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement