Otclient  14/8/2020
shared_ptr.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #ifndef STDEXT_SHARED_PTR_H
24 #define STDEXT_SHARED_PTR_H
25 
26 #include "types.h"
27 #include "dumper.h"
28 #include <type_traits>
29 #include <functional>
30 #include <cassert>
31 #include <ostream>
32 
33 #ifdef THREAD_SAFE
34 #include <atomic>
35 #endif
36 
37 namespace stdext {
38 
39 template<class T>
40 class shared_ptr;
41 
42 template<class T>
43 class weak_ptr;
44 
45 template<class T>
47 {
48 public:
49  shared_base(T* p) : refs(1), weaks(0), px(p) { }
51 
52  void add_ref() { ++refs; }
53  void dec_ref() {
54  if(--refs == 0) {
55  delete px;
56  px = nullptr;
57  if(weaks == 0)
58  delete this;
59  }
60  }
61 
62  void add_weak_ref() { ++weaks; }
63  void dec_weak_ref() {
64  if(--weaks == 0 && refs == 0)
65  delete this;
66  }
67 
68  void set(T *p) {
69  T* tmp = px;
70  px = p;
71  if(tmp)
72  delete tmp;
73  }
74  T *get() { return px; }
75 
76  refcount_t ref_count() { return refs; }
77  refcount_t weak_count() { return weaks; }
78  bool expired() { return refs == 0; }
79 
80 private:
81 #ifdef THREAD_SAFE
82  std::atomic<refcount_t> refs;
83  std::atomic<refcount_t> weaks;
84  std::atomic<T*> px;
85 #else
86  refcount_t refs;
87  refcount_t weaks;
88  T* px;
89 #endif
90 };
91 
92 template<class T>
93 class shared_ptr
94 {
95 public:
96  typedef T element_type;
97 
98  shared_ptr() : base(nullptr) { }
99  shared_ptr(T* p) { if(p != nullptr) base = new shared_base<T>(p); else base = nullptr; }
100  shared_ptr(shared_ptr const& rhs): base(rhs.base) { if(base != nullptr) base->add_ref(); }
101  template<class U>
102  shared_ptr(shared_ptr<U> const& rhs, typename std::is_convertible<U,T>::type* = nullptr) : base(rhs.base) { if(base != nullptr) base->add_ref(); }
103  ~shared_ptr() { if(base != nullptr) base->dec_ref(); }
104 
105  void reset() { shared_ptr().swap(*this); }
106  void reset(T* rhs) { shared_ptr(rhs).swap(*this); }
107  void swap(shared_ptr& rhs) { std::swap(base, rhs.base); }
108 
109  void set(T* p) { assert(p != nullptr); base->set(p); }
110  T* get() const { return base ? base->get() : nullptr; }
111 
112  refcount_t use_count() const { return base ? base->ref_count() : 0; }
113  refcount_t weak_count() const { return base ? base->weak_count() : 0; }
114  bool is_unique() const { return use_count() == 1; }
115 
116  T& operator*() const { assert(base != nullptr); return *base->get(); }
117  T* operator->() const { assert(base != nullptr); return base->get(); }
118 
119  template<class U>
120  shared_ptr& operator=(shared_ptr<U> const& rhs) { shared_ptr(rhs).swap(*this); return *this; }
121  shared_ptr& operator=(shared_ptr const& rhs) { shared_ptr(rhs).swap(*this); return *this; }
122  shared_ptr& operator=(T* rhs) { shared_ptr(rhs).swap(*this); return *this; }
123 
124  // implicit conversion to bool
126  operator unspecified_bool_type() const { return base == nullptr ? nullptr : &shared_ptr::base; }
127  bool operator!() const { return base == nullptr; }
128 
129  // std::move support
130  shared_ptr(shared_ptr&& rhs): base(rhs.base) { rhs.base = nullptr; }
131  shared_ptr& operator=(shared_ptr&& rhs) { shared_ptr(static_cast<shared_ptr&&>(rhs)).swap(*this); return *this; }
132 
133 private:
134  shared_ptr(shared_base<T> *base) {
135  if(base && !base->expired()) {
136  base->add_ref();
137  this->base = base;
138  } else
139  base = nullptr;
140  }
141  shared_base<T> *base;
142 
143  friend class weak_ptr<T>;
144 };
145 
146 template<class T>
147 class weak_ptr {
148 public:
149  typedef T element_type;
150 
151  weak_ptr() : base(nullptr) { }
152  weak_ptr(shared_ptr<T> const& rhs): base(rhs.base) { if(base != nullptr) base->add_weak_ref(); }
153  template<class U>
154  weak_ptr(shared_ptr<U> const& rhs, typename std::is_convertible<U,T>::type* = nullptr) : base(rhs.base) { if(base != nullptr) base->add_weak_ref(); }
155  weak_ptr(weak_ptr<T> const& rhs): base(rhs.base) { if(base != nullptr) base->add_weak_ref(); }
156  template<class U>
157  weak_ptr(weak_ptr<U> const& rhs, typename std::is_convertible<U,T>::type* = nullptr) : base(rhs.base) { if(base != nullptr) base->add_weak_ref(); }
158  ~weak_ptr() { if(base != nullptr) base->dec_weak_ref(); }
159 
160  void reset() { weak_ptr().swap(*this); }
161  void swap(weak_ptr& rhs) { std::swap(base, rhs.base); }
162 
163  T* get() const { return base ? base->get() : nullptr; }
164  refcount_t use_count() const { return base ? base->ref_count() : 0; }
165  refcount_t weak_count() const { return base ? base->weak_count() : 0; }
166  bool expired() const { return base ? base->expired() : false; }
167  shared_ptr<T> lock() { return shared_ptr<T>(base); }
168 
169  weak_ptr& operator=(weak_ptr const& rhs) { weak_ptr(rhs).swap(*this); return *this; }
170  template<class U>
171  weak_ptr& operator=(shared_ptr<U> const& rhs) { weak_ptr(rhs).swap(*this); return *this; }
172  template<class U>
173  weak_ptr& operator=(weak_ptr<T> const& rhs) { weak_ptr(rhs).swap(*this); return *this; }
174 
175  // implicit conversion to bool
177  operator unspecified_bool_type() const { return base == nullptr ? nullptr : &weak_ptr::base; }
178  bool operator!() const { return !expired(); }
179 
180  // std::move support
181  weak_ptr(weak_ptr&& rhs): base(rhs.base) { rhs.base = nullptr; }
182  weak_ptr& operator=(weak_ptr&& rhs) { weak_ptr(static_cast<weak_ptr&&>(rhs)).swap(*this); return *this; }
183 
184 private:
185  shared_base<T> *base;
186 };
187 
188 template<class T, class U> bool operator==(shared_ptr<T> const& a, shared_ptr<U> const& b) { return a.get() == b.get(); }
189 template<class T, class U> bool operator==(weak_ptr<T> const& a, weak_ptr<U> const& b) { return a.get() == b.get(); }
190 template<class T, class U> bool operator==(shared_ptr<T> const& a, weak_ptr<U> const& b) { return a.get() == b.get(); }
191 template<class T, class U> bool operator==(weak_ptr<T> const& a, shared_ptr<U> const& b) { return a.get() == b.get(); }
192 template<class T, class U> bool operator!=(shared_ptr<T> const& a, shared_ptr<U> const& b) { return a.get() != b.get(); }
193 template<class T, class U> bool operator!=(weak_ptr<T> const& a, weak_ptr<U> const& b) { return a.get() != b.get(); }
194 template<class T, class U> bool operator!=(shared_ptr<T> const& a, weak_ptr<U> const& b) { return a.get() != b.get(); }
195 template<class T, class U> bool operator!=(weak_ptr<T> const& a, shared_ptr<U> const& b) { return a.get() != b.get(); }
196 template<class T, class U> bool operator==(shared_ptr<T> const& a, U* b) { return a.get() == b; }
197 template<class T, class U> bool operator==(weak_ptr<T> const& a, U* b) { return a.get() == b; }
198 template<class T, class U> bool operator!=(shared_ptr<T> const& a, U* b) { return a.get() != b; }
199 template<class T, class U> bool operator!=(weak_ptr<T> const& a, U* b) { return a.get() != b; }
200 template<class T, class U> bool operator==(T * a, shared_ptr<U> const& b) { return a == b.get(); }
201 template<class T, class U> bool operator==(T * a, weak_ptr<U> const& b) { return a == b.get(); }
202 template<class T, class U> bool operator!=(T * a, shared_ptr<U> const& b) { return a != b.get(); }
203 template<class T, class U> bool operator!=(T * a, weak_ptr<U> const& b) { return a != b.get(); }
204 template<class T> bool operator<(shared_ptr<T> const& a, shared_ptr<T> const& b) { return std::less<T*>()(a.get(), b.get()); }
205 template<class T> bool operator<(weak_ptr<T> const& a, weak_ptr<T> const& b) { return std::less<T*>()(a.get(), b.get()); }
206 
207 template<class T> T* get_pointer(shared_ptr<T> const& p) { return p.get(); }
208 template<class T> T* get_pointer(weak_ptr<T> const& p) { return p.get(); }
209 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const& p) { return static_cast<T*>(p.get()); }
210 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const& p) { return const_cast<T*>(p.get()); }
211 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& p) { return dynamic_cast<T*>(p.get()); }
212 template<class T, typename... Args> stdext::shared_ptr<T> make_shared(Args... args) { return stdext::shared_ptr<T>(new T(args...)); }
213 
214 // operator<< support
215 template<class E, class T, class Y> std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& os, shared_ptr<Y> const& p) { os << p.get(); return os; }
216 template<class E, class T, class Y> std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& os, weak_ptr<Y> const& p) { os << p.get(); return os; }
217 
218 }
219 
220 namespace std {
221 
222 // hash, for unordered_map support
223 template<typename T> struct hash<stdext::shared_ptr<T>> { size_t operator()(const stdext::shared_ptr<T>& p) const { return std::hash<T*>()(p.get()); } };
224 template<typename T> struct hash<stdext::weak_ptr<T>> { size_t operator()(const stdext::weak_ptr<T>& p) const { return std::hash<T*>()(p.get()); } };
225 
226 // swap support
227 template<class T> void swap(stdext::shared_ptr<T>& lhs, stdext::shared_ptr<T>& rhs) { lhs.swap(rhs); }
228 template<class T> void swap(stdext::weak_ptr<T>& lhs, stdext::weak_ptr<T>& rhs) { lhs.swap(rhs); }
229 
230 }
231 
232 #endif
stdext::weak_ptr::unspecified_bool_type
shared_base< T > *weak_ptr::* unspecified_bool_type
Definition: shared_ptr.h:176
stdext::shared_base::get
T * get()
Definition: shared_ptr.h:74
std::swap
void swap(stdext::packed_vector< T, U > &lhs, stdext::packed_vector< T, U > &rhs)
Definition: packed_vector.h:158
stdext::weak_ptr::reset
void reset()
Definition: shared_ptr.h:160
std::hash< stdext::shared_ptr< T > >::operator()
size_t operator()(const stdext::shared_ptr< T > &p) const
Definition: shared_ptr.h:223
stdext::shared_ptr::shared_ptr
shared_ptr(shared_ptr &&rhs)
Definition: shared_ptr.h:130
stdext::weak_ptr::operator=
weak_ptr & operator=(weak_ptr &&rhs)
Definition: shared_ptr.h:182
types.h
stdext::shared_base
Definition: shared_ptr.h:46
stdext::operator==
bool operator==(shared_object_ptr< T > const &a, shared_object_ptr< U > const &b)
Definition: shared_object.h:111
stdext::const_pointer_cast
shared_object_ptr< T > const_pointer_cast(shared_object_ptr< U > const &p)
Definition: shared_object.h:121
stdext::shared_ptr::operator->
T * operator->() const
Definition: shared_ptr.h:117
stdext::shared_base::shared_base
shared_base(T *p)
Definition: shared_ptr.h:49
stdext::shared_ptr::operator!
bool operator!() const
Definition: shared_ptr.h:127
stdext::shared_ptr::swap
void swap(shared_ptr &rhs)
Definition: shared_ptr.h:107
stdext::operator!=
bool operator!=(shared_object_ptr< T > const &a, shared_object_ptr< U > const &b)
Definition: shared_object.h:112
stdext::weak_ptr
Definition: shared_ptr.h:43
stdext::weak_ptr::lock
shared_ptr< T > lock()
Definition: shared_ptr.h:167
stdext::shared_ptr::operator=
shared_ptr & operator=(shared_ptr< U > const &rhs)
Definition: shared_ptr.h:120
stdext::weak_ptr::~weak_ptr
~weak_ptr()
Definition: shared_ptr.h:158
stdext::shared_ptr::operator*
T & operator*() const
Definition: shared_ptr.h:116
stdext::operator<<
std::basic_ostream< E, T > & operator<<(std::basic_ostream< E, T > &os, shared_object_ptr< Y > const &p)
Definition: shared_object.h:126
stdext::shared_base::~shared_base
~shared_base()
Definition: shared_ptr.h:50
stdext::weak_ptr::weak_ptr
weak_ptr()
Definition: shared_ptr.h:151
refcount_t
uint_fast32_t refcount_t
Definition: types.h:44
stdext::shared_base::ref_count
refcount_t ref_count()
Definition: shared_ptr.h:76
stdext::weak_ptr::weak_count
refcount_t weak_count() const
Definition: shared_ptr.h:165
stdext::weak_ptr::weak_ptr
weak_ptr(weak_ptr &&rhs)
Definition: shared_ptr.h:181
stdext::weak_ptr::element_type
T element_type
Definition: shared_ptr.h:149
stdext::weak_ptr::operator=
weak_ptr & operator=(weak_ptr const &rhs)
Definition: shared_ptr.h:169
stdext::shared_ptr::element_type
T element_type
Definition: shared_ptr.h:96
stdext::get_pointer
T * get_pointer(shared_object_ptr< T > const &p)
Definition: shared_object.h:119
stdext::make_shared
stdext::shared_ptr< T > make_shared(Args... args)
Definition: shared_ptr.h:212
stdext::operator<
bool operator<(shared_object_ptr< T > const &a, shared_object_ptr< T > const &b)
Definition: shared_object.h:117
stdext::shared_ptr::get
T * get() const
Definition: shared_ptr.h:110
stdext::weak_ptr::weak_ptr
weak_ptr(shared_ptr< U > const &rhs, typename std::is_convertible< U, T >::type *=nullptr)
Definition: shared_ptr.h:154
stdext::shared_ptr::shared_ptr
shared_ptr()
Definition: shared_ptr.h:98
stdext::shared_ptr::set
void set(T *p)
Definition: shared_ptr.h:109
stdext::weak_ptr::operator=
weak_ptr & operator=(shared_ptr< U > const &rhs)
Definition: shared_ptr.h:171
stdext::shared_ptr::reset
void reset(T *rhs)
Definition: shared_ptr.h:106
stdext::shared_ptr::unspecified_bool_type
shared_base< T > *shared_ptr::* unspecified_bool_type
Definition: shared_ptr.h:125
stdext::shared_ptr::operator=
shared_ptr & operator=(T *rhs)
Definition: shared_ptr.h:122
stdext::shared_ptr::shared_ptr
shared_ptr(T *p)
Definition: shared_ptr.h:99
stdext::shared_base::add_ref
void add_ref()
Definition: shared_ptr.h:52
stdext::shared_ptr::~shared_ptr
~shared_ptr()
Definition: shared_ptr.h:103
stdext::weak_ptr::swap
void swap(weak_ptr &rhs)
Definition: shared_ptr.h:161
stdext::shared_ptr::shared_ptr
shared_ptr(shared_ptr const &rhs)
Definition: shared_ptr.h:100
stdext::weak_ptr::weak_ptr
weak_ptr(shared_ptr< T > const &rhs)
Definition: shared_ptr.h:152
stdext::shared_base::dec_ref
void dec_ref()
Definition: shared_ptr.h:53
stdext::shared_base::dec_weak_ref
void dec_weak_ref()
Definition: shared_ptr.h:63
stdext::weak_ptr::expired
bool expired() const
Definition: shared_ptr.h:166
stdext::weak_ptr::use_count
refcount_t use_count() const
Definition: shared_ptr.h:164
stdext::shared_base::expired
bool expired()
Definition: shared_ptr.h:78
stdext::shared_base::weak_count
refcount_t weak_count()
Definition: shared_ptr.h:77
stdext::shared_ptr::operator=
shared_ptr & operator=(shared_ptr &&rhs)
Definition: shared_ptr.h:131
stdext::shared_ptr::weak_count
refcount_t weak_count() const
Definition: shared_ptr.h:113
stdext::weak_ptr::operator=
weak_ptr & operator=(weak_ptr< T > const &rhs)
Definition: shared_ptr.h:173
stdext::shared_ptr::shared_ptr
shared_ptr(shared_ptr< U > const &rhs, typename std::is_convertible< U, T >::type *=nullptr)
Definition: shared_ptr.h:102
stdext::shared_base::add_weak_ref
void add_weak_ref()
Definition: shared_ptr.h:62
stdext::weak_ptr::weak_ptr
weak_ptr(weak_ptr< U > const &rhs, typename std::is_convertible< U, T >::type *=nullptr)
Definition: shared_ptr.h:157
stdext::weak_ptr::weak_ptr
weak_ptr(weak_ptr< T > const &rhs)
Definition: shared_ptr.h:155
stdext::weak_ptr::operator!
bool operator!() const
Definition: shared_ptr.h:178
std
Definition: packed_vector.h:157
stdext::shared_ptr::is_unique
bool is_unique() const
Definition: shared_ptr.h:114
std::hash< stdext::weak_ptr< T > >::operator()
size_t operator()(const stdext::weak_ptr< T > &p) const
Definition: shared_ptr.h:224
stdext
Definition: any.h:30
stdext::shared_ptr
Definition: shared_ptr.h:40
stdext::weak_ptr::get
T * get() const
Definition: shared_ptr.h:163
stdext::shared_ptr::use_count
refcount_t use_count() const
Definition: shared_ptr.h:112
stdext::shared_ptr::operator=
shared_ptr & operator=(shared_ptr const &rhs)
Definition: shared_ptr.h:121
dumper.h
stdext::shared_base::set
void set(T *p)
Definition: shared_ptr.h:68
stdext::dynamic_pointer_cast
shared_object_ptr< T > dynamic_pointer_cast(shared_object_ptr< U > const &p)
Definition: shared_object.h:122
stdext::static_pointer_cast
shared_object_ptr< T > static_pointer_cast(shared_object_ptr< U > const &p)
Definition: shared_object.h:120
stdext::shared_ptr::reset
void reset()
Definition: shared_ptr.h:105