Otclient  14/8/2020
shared_object.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_OBJECT_H
24 #define STDEXT_SHARED_OBJECT_H
25 
26 #include "types.h"
27 #include <type_traits>
28 #include <functional>
29 #include <cassert>
30 #include <ostream>
31 
32 #ifdef THREAD_SAFE
33 #include <atomic>
34 #endif
35 
36 namespace stdext {
37 
38 template<class T>
40 
42 {
43 public:
44  shared_object() : refs(0) { }
45  virtual ~shared_object() { }
46  void add_ref() { ++refs; }
47  void dec_ref() { if(--refs == 0) delete this; }
48  refcount_t ref_count() { return refs; }
49 
50  template<typename T> stdext::shared_object_ptr<T> static_self_cast() { return stdext::shared_object_ptr<T>(static_cast<T*>(this)); }
51  template<typename T> stdext::shared_object_ptr<T> dynamic_self_cast() { return stdext::shared_object_ptr<T>(dynamic_cast<T*>(this)); }
52  template<typename T> stdext::shared_object_ptr<T> const_self_cast() { return stdext::shared_object_ptr<T>(const_cast<T*>(this)); }
53 
54 private:
55 #ifdef THREAD_SAFE
56  std::atomic<refcount_t> refs;
57 #else
58  refcount_t refs;
59 #endif
60 };
61 
62 template<class T>
63 class shared_object_ptr
64 {
65 public:
66  typedef T element_type;
67 
68  shared_object_ptr(): px(nullptr) { }
69  shared_object_ptr(T* p, bool add_ref = true) : px(p) {
70  static_assert(std::is_base_of<shared_object, T>::value, "classes using shared_object_ptr must be a derived of stdext::shared_object");
71  if(px != nullptr && add_ref)
72  this->add_ref();
73  }
74  shared_object_ptr(shared_object_ptr const& rhs): px(rhs.px) { if(px != nullptr) add_ref(); }
75  template<class U>
76  shared_object_ptr(shared_object_ptr<U> const& rhs, typename std::enable_if<std::is_convertible<U*,T*>::value, U*>::type = nullptr) : px(rhs.get()) { if(px != nullptr) add_ref(); }
77  ~shared_object_ptr() { if(px != nullptr) dec_ref(); }
78 
79  void reset() { shared_object_ptr().swap(*this); }
80  void reset(T* rhs) { shared_object_ptr(rhs).swap(*this); }
81  void swap(shared_object_ptr& rhs) { std::swap(px, rhs.px); }
82  T* get() const { return px; }
83 
84  refcount_t use_count() const { return ((shared_object*)px)->ref_count(); }
85  bool is_unique() const { return use_count() == 1; }
86 
87  template<class U> shared_object_ptr& operator=(shared_object_ptr<U> const& rhs) { shared_object_ptr(rhs).swap(*this); return *this; }
88 
89  T& operator*() const { assert(px != nullptr); return *px; }
90  T* operator->() const { assert(px != nullptr); return px; }
91 
92  shared_object_ptr& operator=(shared_object_ptr const& rhs) { shared_object_ptr(rhs).swap(*this); return *this; }
93  shared_object_ptr& operator=(T* rhs) { shared_object_ptr(rhs).swap(*this); return *this; }
94 
95  // implicit conversion to bool
97  operator unspecified_bool_type() const { return px == nullptr ? nullptr : &shared_object_ptr::px; }
98  bool operator!() const { return px == nullptr; }
99 
100  // std::move support
101  shared_object_ptr(shared_object_ptr&& rhs): px(rhs.px) { rhs.px = nullptr; }
102  shared_object_ptr& operator=(shared_object_ptr&& rhs) { shared_object_ptr(static_cast<shared_object_ptr&&>(rhs)).swap(*this); return *this; }
103 
104 private:
105  void add_ref() { ((shared_object*)px)->add_ref(); }
106  void dec_ref() { ((shared_object*)px)->dec_ref(); }
107 
108  T* px;
109 };
110 
111 template<class T, class U> bool operator==(shared_object_ptr<T> const& a, shared_object_ptr<U> const& b) { return a.get() == b.get(); }
112 template<class T, class U> bool operator!=(shared_object_ptr<T> const& a, shared_object_ptr<U> const& b) { return a.get() != b.get(); }
113 template<class T, class U> bool operator==(shared_object_ptr<T> const& a, U* b) { return a.get() == b; }
114 template<class T, class U> bool operator!=(shared_object_ptr<T> const& a, U* b) { return a.get() != b; }
115 template<class T, class U> bool operator==(T * a, shared_object_ptr<U> const& b) { return a == b.get(); }
116 template<class T, class U> bool operator!=(T * a, shared_object_ptr<U> const& b) { return a != b.get(); }
117 template<class T> bool operator<(shared_object_ptr<T> const& a, shared_object_ptr<T> const& b) { return std::less<T*>()(a.get(), b.get()); }
118 
119 template<class T> T* get_pointer(shared_object_ptr<T> const& p) { return p.get(); }
120 template<class T, class U> shared_object_ptr<T> static_pointer_cast(shared_object_ptr<U> const& p) { return static_cast<T*>(p.get()); }
121 template<class T, class U> shared_object_ptr<T> const_pointer_cast(shared_object_ptr<U> const& p) { return const_cast<T*>(p.get()); }
122 template<class T, class U> shared_object_ptr<T> dynamic_pointer_cast(shared_object_ptr<U> const& p) { return dynamic_cast<T*>(p.get()); }
123 template<class T, typename... Args> stdext::shared_object_ptr<T> make_shared_object(Args... args) { return stdext::shared_object_ptr<T>(new T(args...)); }
124 
125 // operator<< support
126 template<class E, class T, class Y> std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& os, shared_object_ptr<Y> const& p) { os << p.get(); return os; }
127 
128 }
129 
130 namespace std {
131 
132 // hash, for unordered_map support
133 template<typename T> struct hash<stdext::shared_object_ptr<T>> { size_t operator()(const stdext::shared_object_ptr<T>& p) const { return std::hash<T*>()(p.get()); } };
134 
135 // swap support
136 template<class T> void swap(stdext::shared_object_ptr<T>& lhs, stdext::shared_object_ptr<T>& rhs) { lhs.swap(rhs); }
137 
138 }
139 
140 #endif
stdext::shared_object_ptr::shared_object_ptr
shared_object_ptr(shared_object_ptr &&rhs)
Definition: shared_object.h:101
stdext::shared_object_ptr::operator!
bool operator!() const
Definition: shared_object.h:98
std::swap
void swap(stdext::packed_vector< T, U > &lhs, stdext::packed_vector< T, U > &rhs)
Definition: packed_vector.h:158
types.h
stdext::shared_object_ptr::operator*
T & operator*() const
Definition: shared_object.h:89
stdext::shared_object_ptr::operator=
shared_object_ptr & operator=(T *rhs)
Definition: shared_object.h:93
stdext::operator==
bool operator==(shared_object_ptr< T > const &a, shared_object_ptr< U > const &b)
Definition: shared_object.h:111
stdext::shared_object::ref_count
refcount_t ref_count()
Definition: shared_object.h:48
std::hash< stdext::shared_object_ptr< T > >::operator()
size_t operator()(const stdext::shared_object_ptr< T > &p) const
Definition: shared_object.h:133
stdext::const_pointer_cast
shared_object_ptr< T > const_pointer_cast(shared_object_ptr< U > const &p)
Definition: shared_object.h:121
stdext::shared_object_ptr::use_count
refcount_t use_count() const
Definition: shared_object.h:84
stdext::shared_object_ptr::~shared_object_ptr
~shared_object_ptr()
Definition: shared_object.h:77
stdext::shared_object_ptr::operator=
shared_object_ptr & operator=(shared_object_ptr const &rhs)
Definition: shared_object.h:92
stdext::operator!=
bool operator!=(shared_object_ptr< T > const &a, shared_object_ptr< U > const &b)
Definition: shared_object.h:112
stdext::shared_object::add_ref
void add_ref()
Definition: shared_object.h:46
stdext::shared_object::const_self_cast
stdext::shared_object_ptr< T > const_self_cast()
Definition: shared_object.h:52
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
refcount_t
uint_fast32_t refcount_t
Definition: types.h:44
stdext::shared_object_ptr::shared_object_ptr
shared_object_ptr(T *p, bool add_ref=true)
Definition: shared_object.h:69
stdext::shared_object_ptr::is_unique
bool is_unique() const
Definition: shared_object.h:85
stdext::get_pointer
T * get_pointer(shared_object_ptr< T > const &p)
Definition: shared_object.h:119
stdext::operator<
bool operator<(shared_object_ptr< T > const &a, shared_object_ptr< T > const &b)
Definition: shared_object.h:117
stdext::shared_object::shared_object
shared_object()
Definition: shared_object.h:44
stdext::shared_object::dec_ref
void dec_ref()
Definition: shared_object.h:47
stdext::shared_object_ptr::operator=
shared_object_ptr & operator=(shared_object_ptr< U > const &rhs)
Definition: shared_object.h:87
stdext::shared_object_ptr::reset
void reset()
Definition: shared_object.h:79
stdext::shared_object_ptr::element_type
T element_type
Definition: shared_object.h:66
stdext::shared_object::static_self_cast
stdext::shared_object_ptr< T > static_self_cast()
Definition: shared_object.h:50
stdext::shared_object_ptr::operator->
T * operator->() const
Definition: shared_object.h:90
stdext::shared_object_ptr::swap
void swap(shared_object_ptr &rhs)
Definition: shared_object.h:81
stdext::make_shared_object
stdext::shared_object_ptr< T > make_shared_object(Args... args)
Definition: shared_object.h:123
stdext::shared_object::dynamic_self_cast
stdext::shared_object_ptr< T > dynamic_self_cast()
Definition: shared_object.h:51
stdext::shared_object_ptr::operator=
shared_object_ptr & operator=(shared_object_ptr &&rhs)
Definition: shared_object.h:102
stdext::shared_object_ptr::unspecified_bool_type
T *shared_object_ptr::* unspecified_bool_type
Definition: shared_object.h:96
stdext::shared_object_ptr::reset
void reset(T *rhs)
Definition: shared_object.h:80
std
Definition: packed_vector.h:157
stdext::shared_object_ptr
Definition: shared_object.h:39
stdext::shared_object_ptr::shared_object_ptr
shared_object_ptr()
Definition: shared_object.h:68
stdext
Definition: any.h:30
stdext::shared_object::~shared_object
virtual ~shared_object()
Definition: shared_object.h:45
stdext::shared_object
Definition: shared_object.h:41
stdext::shared_object_ptr::get
T * get() const
Definition: shared_object.h:82
stdext::shared_object_ptr::shared_object_ptr
shared_object_ptr(shared_object_ptr< U > const &rhs, typename std::enable_if< std::is_convertible< U *, T * >::value, U * >::type=nullptr)
Definition: shared_object.h:76
stdext::shared_object_ptr::shared_object_ptr
shared_object_ptr(shared_object_ptr const &rhs)
Definition: shared_object.h:74
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