nx_server_plugin_sdk  1.0
Server Plugin SDK
ptr.h
1 // Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/
2 
3 #pragma once
4 
5 #include <cstddef>
6 #include <type_traits>
7 #include <utility>
8 
9 namespace nx {
10 namespace sdk {
11 
17 template<class RefCountable>
18 class Ptr final
19 {
20 public:
22  Ptr(std::nullptr_t = nullptr)
23  {
24  // This assertion needs to be placed in any method because it uses sizeof().
25  static_assert(sizeof(Ptr<RefCountable>) == sizeof(RefCountable*),
26  "Ptr layout should be the same as of a raw pointer.");
27  }
28 
29  explicit Ptr(RefCountable* ptr): m_ptr(ptr) {}
30 
31  template<class OtherRefCountable>
32  explicit Ptr(OtherRefCountable* ptr): m_ptr(ptr) {}
33 
34  template<class OtherRefCountable>
35  Ptr(const Ptr<OtherRefCountable>& other): m_ptr(other.get()) { addRef(); }
36 
38  Ptr(const Ptr& other): m_ptr(other.get()) { addRef(); }
39 
40  template<class OtherRefCountable>
41  Ptr(Ptr<OtherRefCountable>&& other): m_ptr(other.releasePtr()) {}
42 
44  Ptr(Ptr&& other) noexcept: m_ptr(other.releasePtr()) {}
45 
46  template<class OtherRefCountable>
47  Ptr& operator=(const Ptr<OtherRefCountable>& other) { return assignConst(other); }
48 
50  Ptr& operator=(const Ptr& other) { return assignConst(other); }
51 
52  template<class OtherRefCountable>
53  Ptr& operator=(Ptr<OtherRefCountable>&& other) { return assignRvalue(std::move(other)); }
54 
56  Ptr& operator=(Ptr&& other) noexcept { return assignRvalue(std::move(other)); }
57 
58  ~Ptr() { releaseRef(); }
59 
60  template<class OtherRefCountable>
61  bool operator==(const Ptr<OtherRefCountable>& other) const { return m_ptr == other.get(); }
62 
63  template<class OtherRefCountable>
64  bool operator!=(const Ptr<OtherRefCountable>& other) const { return !operator==(other); }
65 
70  void reset()
71  {
72  releaseRef();
73  m_ptr = nullptr;
74  }
75 
80  template<class OtherRefCountable>
81  void reset(OtherRefCountable* ptr)
82  {
83  releaseRef();
84  m_ptr = ptr;
85  }
86 
93  {
94  RefCountable* result = m_ptr;
95  m_ptr = nullptr;
96  return result;
97  }
98 
99  RefCountable* get() const { return m_ptr; }
100  RefCountable* operator->() const { return m_ptr; }
101  RefCountable& operator*() const { return *m_ptr; }
102 
103  explicit operator bool() const { return m_ptr != nullptr; }
104 
105 private:
106  void addRef()
107  {
108  if (m_ptr)
109  m_ptr->addRef();
110  }
111 
112  void releaseRef()
113  {
114  if (m_ptr)
115  m_ptr->releaseRef();
116  }
117 
118  Ptr& assignConst(const Ptr& other)
119  {
120  if (this != &other && m_ptr != other.get())
121  {
122  releaseRef();
123  m_ptr = other.get();
124  addRef();
125  }
126  return *this;
127  }
128 
129  Ptr& assignRvalue(Ptr&& other)
130  {
131  if (this != &other && m_ptr != other.get())
132  {
133  releaseRef();
134  m_ptr = other.releasePtr();
135  }
136  return *this;
137  }
138 
139 private:
140  RefCountable* m_ptr = nullptr;
141 };
142 
143 template<class RefCountable, typename Object>
144 bool operator==(const Ptr<RefCountable>& ptr, Object* p) { return ptr.get() == p; }
145 
146 template<typename Object, class RefCountable>
147 bool operator==(Object* p, const Ptr<RefCountable>& ptr) { return p == ptr.get(); }
148 
149 template<class RefCountable, typename Object>
150 bool operator!=(const Ptr<RefCountable>& ptr, Object* p) { return ptr.get() != p; }
151 
152 template<typename Object, class RefCountable>
153 bool operator!=(Object* p, const Ptr<RefCountable>& ptr) { return p != ptr.get(); }
154 
155 template<class RefCountable>
156 bool operator==(const Ptr<RefCountable>& ptr, std::nullptr_t) { return !ptr; }
157 
158 template<class RefCountable>
159 bool operator==(std::nullptr_t, const Ptr<RefCountable>& ptr) { return !ptr; }
160 
161 template<class RefCountable>
162 bool operator!=(const Ptr<RefCountable>& ptr, std::nullptr_t) { return (bool) ptr; }
163 
164 template<class RefCountable>
165 bool operator!=(std::nullptr_t, const Ptr<RefCountable>& ptr) { return (bool) ptr; }
166 
167 template<typename First, typename Second>
168 bool operator<(const Ptr<First>& first, const Ptr<Second>& second)
169 {
170  return first.get() < second.get();
171 }
172 
173 template<typename RefCountable>
174 bool operator<(const Ptr<RefCountable>& refCountable, std::nullptr_t)
175 {
176  return refCountable.get() < nullptr;
177 }
178 
179 template<typename RefCountable>
180 bool operator<(std::nullptr_t, const Ptr<RefCountable>& refCountable)
181 {
182  return nullptr < refCountable.get();
183 }
184 
185 template<typename First, typename Second>
186 bool operator<(const Ptr<First>& first, const Second* second)
187 {
188  return first.get() < second;
189 }
190 
191 template<typename First, typename Second>
192 bool operator<(const First* first, const Ptr<Second>& second)
193 {
194  return first < second.get();
195 }
196 
201 template<class RefCountable>
202 static Ptr<RefCountable> shareToPtr(RefCountable* refCountable)
203 {
204  if (refCountable)
205  refCountable->addRef();
206  return Ptr(refCountable);
207 }
208 
213 template<class RefCountable>
214 static Ptr<RefCountable> shareToPtr(const Ptr<RefCountable>& ptr)
215 {
216  return ptr; //< Invoke the copy constructor.
217 }
218 
222 template<class RefCountable, typename... Args>
223 static Ptr<RefCountable> makePtr(Args&&... args)
224 {
225  return Ptr(new RefCountable(std::forward<Args>(args)...));
226 }
227 
232 template</*explicit*/ class NewRefCountable, /*deduced*/ class OldRefCountable>
233 static Ptr<NewRefCountable> reinterpretPtr(const Ptr<OldRefCountable>& ptr)
234 {
235  return shareToPtr(reinterpret_cast<NewRefCountable*>(ptr.get()));
236 }
237 
242 template</*explicit*/ class Interface, /*deduced*/ class RefCountablePtr,
243  /*deduced*/ typename OldInterfaceId>
244 static Ptr<Interface> queryInterfaceOfOldSdk(
245  RefCountablePtr refCountable, const OldInterfaceId& interfaceId)
246 {
247  return refCountable
248  ? Ptr(static_cast<Interface*>(refCountable->queryInterface(interfaceId)))
249  : nullptr;
250 }
251 
256 template<class RefCountable>
257 static int refCount(const Ptr<RefCountable>& ptr)
258 {
259  return refCount(ptr.get());
260 }
261 
262 } // namespace sdk
263 } // namespace nx
RefCountable * releasePtr()
Definition: ptr.h:92
Definition: ptr.h:18
Ptr(std::nullptr_t=nullptr)
Definition: ptr.h:22
Ptr & operator=(const Ptr &other)
Definition: ptr.h:50
Definition: apple_utils.h:6
Ptr & operator=(Ptr &&other) noexcept
Definition: ptr.h:56
Ptr(const Ptr &other)
Definition: ptr.h:38
void reset(OtherRefCountable *ptr)
Definition: ptr.h:81
Definition: ref_countable.h:83
void reset()
Definition: ptr.h:70
Ptr(Ptr &&other) noexcept
Definition: ptr.h:44