Advertisement
AntonGorokhov

Untitled

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