| LEFT | RIGHT | 
| (no file at all) |  | 
 |    1 // Parts of this code have been copied from boost/smart_ptr/intrusive_ptr.hpp. | 
 |    2 // | 
 |    3 //  Copyright (c) 2001, 2002 Peter Dimov | 
 |    4 // | 
 |    5 // Distributed under the Boost Software License, Version 1.0. (See | 
 |    6 // accompanying file LICENSE_1_0.txt or copy at | 
 |    7 // http://www.boost.org/LICENSE_1_0.txt) | 
 |    8  | 
 |    9 #pragma once | 
 |   10  | 
 |   11 #include <algorithm> | 
 |   12 #include <type_traits> | 
 |   13  | 
 |   14 #include "debug.h" | 
 |   15  | 
 |   16 class ref_counted | 
 |   17 { | 
 |   18 public: | 
 |   19   void AddRef() | 
 |   20   { | 
 |   21     mRefCount++; | 
 |   22   } | 
 |   23  | 
 |   24   void ReleaseRef() | 
 |   25   { | 
 |   26     assert(mRefCount > 0, u"Unexpected zero or negative reference count"_str); | 
 |   27     if (--mRefCount == 0) | 
 |   28       delete this; | 
 |   29   } | 
 |   30  | 
 |   31 protected: | 
 |   32   ref_counted() | 
 |   33       : mRefCount(1) | 
 |   34   { | 
 |   35   } | 
 |   36  | 
 |   37   virtual ~ref_counted() | 
 |   38   { | 
 |   39     assert(mRefCount == 0, u"Destroying a ref-counted object with a non-zero ref
     erence count"_str); | 
 |   40   } | 
 |   41  | 
 |   42 private: | 
 |   43   int mRefCount; | 
 |   44 }; | 
 |   45  | 
 |   46 template<typename T, | 
 |   47     class = typename std::enable_if<std::is_base_of<ref_counted,T>::value>::type
     > | 
 |   48 class intrusive_ptr | 
 |   49 { | 
 |   50 public: | 
 |   51   explicit intrusive_ptr() | 
 |   52       : mPointer(nullptr) | 
 |   53   { | 
 |   54   } | 
 |   55  | 
 |   56   explicit intrusive_ptr(T* pointer) | 
 |   57       : mPointer(pointer) | 
 |   58   { | 
 |   59     // Raw pointers always had their reference count increased by whatever gave | 
 |   60     // us the pointer so we don't need to do it here. | 
 |   61   } | 
 |   62  | 
 |   63   intrusive_ptr(const intrusive_ptr& other) | 
 |   64       : mPointer(other.mPointer) | 
 |   65   { | 
 |   66     if (mPointer) | 
 |   67       mPointer->AddRef(); | 
 |   68   } | 
 |   69  | 
 |   70   intrusive_ptr(intrusive_ptr&& other) | 
 |   71       : mPointer(other.mPointer) | 
 |   72   { | 
 |   73     other.mPointer = nullptr; | 
 |   74   } | 
 |   75  | 
 |   76   ~intrusive_ptr() | 
 |   77   { | 
 |   78     if (mPointer) | 
 |   79       mPointer->ReleaseRef(); | 
 |   80   } | 
 |   81  | 
 |   82   intrusive_ptr& operator=(intrusive_ptr& other) | 
 |   83   { | 
 |   84     intrusive_ptr(other).swap(*this); | 
 |   85     return *this; | 
 |   86   } | 
 |   87  | 
 |   88   intrusive_ptr& operator=(intrusive_ptr&& other) | 
 |   89   { | 
 |   90     intrusive_ptr(std::move(other)).swap(*this); | 
 |   91     return *this; | 
 |   92   } | 
 |   93  | 
 |   94   intrusive_ptr& operator=(T* other) | 
 |   95   { | 
 |   96     intrusive_ptr(other).swap(*this); | 
 |   97     return *this; | 
 |   98   } | 
 |   99  | 
 |  100   void reset() | 
 |  101   { | 
 |  102     intrusive_ptr().swap(*this); | 
 |  103   } | 
 |  104  | 
 |  105   void reset(T* other) | 
 |  106   { | 
 |  107     intrusive_ptr(other).swap(*this); | 
 |  108   } | 
 |  109  | 
 |  110   const T* get() const | 
 |  111   { | 
 |  112     return mPointer; | 
 |  113   } | 
 |  114  | 
 |  115   T* get() | 
 |  116   { | 
 |  117     return mPointer; | 
 |  118   } | 
 |  119  | 
 |  120   const T& operator*() const | 
 |  121   { | 
 |  122     return *mPointer; | 
 |  123   } | 
 |  124  | 
 |  125   T& operator*() | 
 |  126   { | 
 |  127     return *mPointer; | 
 |  128   } | 
 |  129  | 
 |  130   const T* operator->() const | 
 |  131   { | 
 |  132     return mPointer; | 
 |  133   } | 
 |  134  | 
 |  135   T* operator->() | 
 |  136   { | 
 |  137     return mPointer; | 
 |  138   } | 
 |  139  | 
 |  140   explicit operator bool() const | 
 |  141   { | 
 |  142     return mPointer != nullptr; | 
 |  143   } | 
 |  144  | 
 |  145   bool operator!() const | 
 |  146   { | 
 |  147     return mPointer == nullptr; | 
 |  148   } | 
 |  149  | 
 |  150   T* release() | 
 |  151   { | 
 |  152     T* result = mPointer; | 
 |  153     mPointer = nullptr; | 
 |  154     return result; | 
 |  155   } | 
 |  156  | 
 |  157   void swap(intrusive_ptr& other) | 
 |  158   { | 
 |  159     std::swap(mPointer, other.mPointer); | 
 |  160   } | 
 |  161  | 
 |  162 private: | 
 |  163   T* mPointer; | 
 |  164 }; | 
 |  165  | 
 |  166 template<typename T, typename U> | 
 |  167 inline bool operator==(const intrusive_ptr<T>& a, const intrusive_ptr<U>& b) | 
 |  168 { | 
 |  169   return a.get() == b.get(); | 
 |  170 } | 
 |  171  | 
 |  172 template<typename T, typename U> | 
 |  173 inline bool operator!=(const intrusive_ptr<T>& a, const intrusive_ptr<U>& b) | 
 |  174 { | 
 |  175   return a.get() != b.get(); | 
 |  176 } | 
 |  177  | 
 |  178 template<typename T, typename U> | 
 |  179 inline bool operator==(const intrusive_ptr<T>& a, const U* b) | 
 |  180 { | 
 |  181   return a.get() == b; | 
 |  182 } | 
 |  183  | 
 |  184 template<typename T, typename U> | 
 |  185 inline bool operator!=(const intrusive_ptr<T>& a, const U* b) | 
 |  186 { | 
 |  187     return a.get() != b; | 
 |  188 } | 
 |  189  | 
 |  190 template<typename T, typename U> | 
 |  191 inline bool operator==(const T* a, const intrusive_ptr<U>& b) | 
 |  192 { | 
 |  193   return a == b.get(); | 
 |  194 } | 
 |  195  | 
 |  196 template<typename T, typename U> | 
 |  197 inline bool operator!=(const T* a, intrusive_ptr<U> const& b) | 
 |  198 { | 
 |  199   return a != b.get(); | 
 |  200 } | 
| LEFT | RIGHT |