nx_metadata_sdk  1.0
Metadata 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 <utility>
6 #include <cstddef>
7 #include <type_traits>
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  template<class OtherRefCountable>
30  Ptr(const Ptr<OtherRefCountable>& other): m_ptr(other.get()) { addRef(); }
31 
33  Ptr(const Ptr& other): m_ptr(other.get()) { addRef(); }
34 
35  template<class OtherRefCountable>
36  Ptr(Ptr<OtherRefCountable>&& other): m_ptr(other.releasePtr()) {}
37 
39  Ptr(Ptr&& other): m_ptr(other.releasePtr()) {}
40 
41  template<class OtherRefCountable>
42  Ptr& operator=(const Ptr<OtherRefCountable>& other) { return assignConst(other); }
43 
45  Ptr& operator=(const Ptr& other) { return assignConst(other); }
46 
47  template<class OtherRefCountable>
48  Ptr& operator=(Ptr<OtherRefCountable>&& other) { return assignRvalue(std::move(other)); }
49 
51  Ptr& operator=(Ptr&& other) { return assignRvalue(std::move(other)); }
52 
53  ~Ptr() { releaseRef(); }
54 
55  template<class OtherRefCountable>
56  bool operator==(const Ptr<OtherRefCountable>& other) const { return m_ptr == other.get(); }
57 
58  template<class OtherRefCountable>
59  bool operator!=(const Ptr<OtherRefCountable>& other) const { return !operator==(other); }
60 
65  void reset()
66  {
67  releaseRef();
68  m_ptr = nullptr;
69  }
70 
75  template<class OtherRefCountable>
76  void reset(OtherRefCountable* ptr)
77  {
78  releaseRef();
79  m_ptr = ptr;
80  }
81 
88  {
89  RefCountable* result = m_ptr;
90  m_ptr = nullptr;
91  return result;
92  }
93 
94  RefCountable* get() const { return m_ptr; }
95  RefCountable* operator->() const { return m_ptr; }
96  RefCountable& operator*() const { return *m_ptr; }
97 
98  explicit operator bool() const { return m_ptr != nullptr; }
99 
100 private:
101  template<class OtherRefCountable>
102  friend Ptr<OtherRefCountable> toPtr(OtherRefCountable* refCountable);
103 
104  explicit Ptr(RefCountable* ptr): m_ptr(ptr) {}
105 
106  template<class OtherRefCountable>
107  explicit Ptr(OtherRefCountable* ptr): m_ptr(ptr) {}
108 
109  void addRef()
110  {
111  if (m_ptr)
112  m_ptr->addRef();
113  }
114 
115  void releaseRef()
116  {
117  if (m_ptr)
118  m_ptr->releaseRef();
119  }
120 
121  Ptr& assignConst(const Ptr& other)
122  {
123  if (this != &other && m_ptr != other.get())
124  {
125  releaseRef();
126  m_ptr = other.get();
127  addRef();
128  }
129  return *this;
130  }
131 
132  Ptr& assignRvalue(Ptr&& other)
133  {
134  if (this != &other && m_ptr != other.get())
135  {
136  releaseRef();
137  m_ptr = other.releasePtr();
138  }
139  return *this;
140  }
141 
142 private:
143  RefCountable* m_ptr = nullptr;
144 };
145 
146 template<class RefCountable, typename Object>
147 bool operator==(const Ptr<RefCountable>& ptr, Object* p) { return ptr.get() == p; }
148 
149 template<typename Object, class RefCountable>
150 bool operator==(Object* p, const Ptr<RefCountable>& ptr) { return p == ptr.get(); }
151 
152 template<class RefCountable, typename Object>
153 bool operator!=(const Ptr<RefCountable>& ptr, Object* p) { return ptr.get() != p; }
154 
155 template<typename Object, class RefCountable>
156 bool operator!=(Object* p, const Ptr<RefCountable>& ptr) { return p != ptr.get(); }
157 
158 template<class RefCountable>
159 bool operator==(const Ptr<RefCountable>& ptr, std::nullptr_t) { return !ptr; }
160 
161 template<class RefCountable>
162 bool operator==(std::nullptr_t, const Ptr<RefCountable>& ptr) { return !ptr; }
163 
164 template<class RefCountable>
165 bool operator!=(const Ptr<RefCountable>& ptr, std::nullptr_t) { return (bool) ptr; }
166 
167 template<class RefCountable>
168 bool operator!=(std::nullptr_t, const Ptr<RefCountable>& ptr) { return (bool) ptr; }
169 
170 template<typename RefCountable>
171 bool operator<(const Ptr<const RefCountable>& first, const Ptr<const RefCountable>& second)
172 {
173  return first.get() < second.get();
174 }
175 
176 template<typename RefCountable>
177 bool operator<(const Ptr<const RefCountable>& refCountable, std::nullptr_t)
178 {
179  return refCountable.get() < nullptr;
180 }
181 
182 template<typename RefCountable>
183 bool operator<(std::nullptr_t, const Ptr<RefCountable>& refCountable)
184 {
185  return nullptr < refCountable.get();
186 }
187 
194 template<class RefCountable>
195 static Ptr<RefCountable> toPtr(RefCountable* refCountable)
196 {
197  return Ptr<RefCountable>(refCountable);
198 }
199 
204 template<class RefCountable>
205 static Ptr<RefCountable> shareToPtr(RefCountable* refCountable)
206 {
207  if (refCountable)
208  refCountable->addRef();
209  return toPtr(refCountable);
210 }
211 
216 template<class RefCountable>
217 static Ptr<RefCountable> shareToPtr(const Ptr<RefCountable>& ptr)
218 {
219  return ptr; //< Invoke the copy constructor.
220 }
221 
225 template<class RefCountable, typename... Args>
226 static Ptr<RefCountable> makePtr(Args&&... args)
227 {
228  return toPtr(new RefCountable(std::forward<Args>(args)...));
229 }
230 
235 template</*explicit*/ class Interface, /*deduced*/ class RefCountablePtr,
236  /*deduced*/ typename OldInterfaceId>
237 static Ptr<Interface> queryInterfaceOfOldSdk(
238  RefCountablePtr refCountable, const OldInterfaceId& interfaceId)
239 {
240  return refCountable
241  ? toPtr(static_cast<Interface*>(refCountable->queryInterface(interfaceId)))
242  : nullptr;
243 }
244 
249 template<class RefCountable>
250 int refCount(const Ptr<RefCountable>& ptr)
251 {
252  return refCount(ptr.get());
253 }
254 
255 } // namespace sdk
256 } // namespace nx
Ptr(Ptr &&other)
Definition: ptr.h:39
RefCountable * releasePtr()
Definition: ptr.h:87
Definition: ptr.h:18
Ptr(std::nullptr_t=nullptr)
Definition: ptr.h:22
Ptr & operator=(Ptr &&other)
Definition: ptr.h:51
Ptr & operator=(const Ptr &other)
Definition: ptr.h:45
Definition: apple_utils.h:6
Ptr(const Ptr &other)
Definition: ptr.h:33
void reset(OtherRefCountable *ptr)
Definition: ptr.h:76
Definition: ref_countable.h:84
void reset()
Definition: ptr.h:65