Advertisement
AntonGorokhov

Untitled

Oct 1st, 2022
792
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.01 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.         if (block_) {
  241.             --block_->cnt;
  242.             if (block_->cnt == 0 && block_->cnt_weak == 0) {
  243.                 delete block_;
  244.             } else {
  245.                 if (block_->cnt == 0) {
  246.                     if constexpr (std::is_base_of_v<ESFTBase, T>) {
  247.                         block_->DeletePtr(true);
  248.                     } else {
  249.                         block_->DeletePtr();
  250.                         if (block_->cnt == 0 && block_->cnt_weak == 0) {
  251.                             delete block_;
  252.                         }
  253.                     }
  254.                 }
  255.             }
  256.         }
  257.     }
  258.  
  259.     ////////////////////////////////////////////////////////////////////////////////////////////////
  260.     // Modifiers
  261.  
  262.     void Reset() {
  263.         auto prev = block_;
  264.         block_ = nullptr;
  265.         if (prev) {
  266.             --prev->cnt;
  267.             if (prev->cnt == 0 && prev->cnt_weak == 0) {
  268.                 delete prev;
  269.             } else {
  270.                 if (prev->cnt == 0) {
  271.                     prev->DeletePtr();
  272.                     if (prev->cnt == 0 && prev->cnt_weak == 0) {
  273.                         delete prev;
  274.                     }
  275.                 }
  276.             }
  277.         }
  278.         ptr_ = nullptr;
  279.     }
  280.     void Reset(T* ptr) {
  281.         auto prev = block_;
  282.         block_ = nullptr;
  283.         if (prev) {
  284.             --prev->cnt;
  285.             if (prev->cnt == 0 && prev->cnt_weak == 0) {
  286.                 delete prev;
  287.             } else {
  288.                 if (prev->cnt == 0) {
  289.                     prev->DeletePtr();
  290.                     if (prev->cnt == 0 && prev->cnt_weak == 0) {
  291.                         delete prev;
  292.                     }
  293.                 }
  294.             }
  295.         }
  296.         block_ = new Block(ptr);
  297.         ptr_ = ptr;
  298.     }
  299.     template <typename Y>
  300.     void Reset(Y* ptr) {
  301.         auto prev = block_;
  302.         block_ = nullptr;
  303.         if (prev) {
  304.             --prev->cnt;
  305.             if (prev->cnt == 0 && prev->cnt_weak == 0) {
  306.                 delete prev;
  307.             } else {
  308.                 if (prev->cnt == 0) {
  309.                     prev->DeletePtr();
  310.                     if (prev->cnt == 0 && prev->cnt_weak == 0) {
  311.                         delete prev;
  312.                     }
  313.                 }
  314.             }
  315.         }
  316.         block_ = new Block<Y>(ptr);
  317.         ptr_ = ptr;
  318.     }
  319.     void Swap(SharedPtr& other) {
  320.         std::swap(block_, other.block_);
  321.         std::swap(ptr_, other.ptr_);
  322.     }
  323.  
  324.     ////////////////////////////////////////////////////////////////////////////////////////////////
  325.     // Observers
  326.  
  327.     T* Get() const {
  328.         if (block_ && block_->deleted) {
  329.             return nullptr;
  330.         }
  331.         return ptr_;
  332.     }
  333.     T& operator*() const {
  334.         return *ptr_;
  335.     }
  336.     T* operator->() const {
  337.         return Get();
  338.     }
  339.     size_t UseCount() const {
  340.         if (!block_) {
  341.             return 0;
  342.         }
  343.         return block_->cnt;
  344.     }
  345.     explicit operator bool() const {
  346.         return block_;
  347.     }
  348.     BlockBase* block_ = nullptr;
  349. };
  350.  
  351. template <typename T, typename U>
  352. inline bool operator==(const SharedPtr<T>& left, const SharedPtr<U>& right) {
  353.     return left.block_ == right.block_;
  354. }
  355.  
  356. // Allocate memory only once
  357. template <typename T, typename... Args>
  358. SharedPtr<T> MakeShared(Args&&... args);
  359.  
  360. // Look for usage examples in tests
  361. template <typename T>
  362. class EnableSharedFromThis : ESFTBase {
  363. public:
  364.     SharedPtr<T> SharedFromThis() {
  365.         return SharedPtr(weak_this.block_, weak_this.ptr_, true);
  366.     }
  367.     SharedPtr<const T> SharedFromThis() const;
  368.  
  369.     WeakPtr<T> WeakFromThis() noexcept {
  370.         return weak_this;
  371.     }
  372.     WeakPtr<const T> WeakFromThis() const noexcept {
  373.         return WeakPtr<const T>(weak_this);
  374.     }
  375.     WeakPtr<T> weak_this;
  376. };
  377.  
  378. template <typename T, typename... Args>
  379. SharedPtr<T> MakeShared(Args&&... args) {
  380.     auto block = new BlockEmplace<T>(std::forward<Args>(args)...);
  381.     return SharedPtr<T>(block, block->Get());
  382. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement