NAP
objectptr.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 #pragma once
6 
7 // External Includes
8 #include <utility/dllexport.h>
9 #include <unordered_set>
10 #include <rtti/object.h>
11 #include <cassert>
12 #include <mutex>
13 
14 namespace nap
15 {
16  namespace rtti
17  {
23  class NAPAPI ObjectPtrBase
24  {
25  RTTI_ENABLE()
26  public:
27  virtual ~ObjectPtrBase() = default;
28 
32  rttr::type getWrappedType() const { return mPtr->get_type(); }
33 
34  private:
35  ObjectPtrBase() = default;
36 
41  mPtr(ptr) { }
42 
46  rtti::Object* get() { return mPtr; }
47 
51  const rtti::Object* get() const { return mPtr; }
52 
53  private:
57  void set(rtti::Object* ptr)
58  {
59  if (mPtr != nullptr)
60  mPtr->decrementObjectPtrRefCount();
61 
62  mPtr = ptr;
63 
64  if (mPtr != nullptr)
65  mPtr->incrementObjectPtrRefCount();
66  }
67  private:
68  template<class T> friend class ObjectPtr;
69  friend class ObjectPtrManager;
70  rtti::Object* mPtr = nullptr;
71  };
72 
73 
89  class NAPAPI ObjectPtrManager
90  {
91  public:
92  typedef std::unordered_set<ObjectPtrBase*> ObjectPtrSet;
93 
97  static ObjectPtrManager& get();
98 
104  template<class OBJECTSBYIDMAP>
105  void patchPointers(OBJECTSBYIDMAP& newTargetObjects);
106 
111  void resetPointers(const rtti::Object& targetObject)
112  {
113  for (ObjectPtrBase* ptr : mObjectPointers)
114  {
115  if (ptr->get() == &targetObject)
116  ptr->set(nullptr);
117  }
118  }
119 
120  private:
121  template<class T> friend class ObjectPtr;
122 
126  void add(ObjectPtrBase& ptr) { mObjectPointers.insert(&ptr); }
127 
131  void remove(ObjectPtrBase& ptr) { mObjectPointers.erase(&ptr); }
132 
133  ObjectPtrSet mObjectPointers;
134  };
135 
149  template<typename T>
150  class ObjectPtr : public ObjectPtrBase
151  {
152  RTTI_ENABLE(ObjectPtrBase)
153 
154  public:
155  // Default constructor
156  ObjectPtr() = default;
157 
158  // Dtor
159  virtual ~ObjectPtr() override;
160 
161  // Regular ptr Ctor
162  ObjectPtr(T* ptr);
163 
164  // Copy ctor
165  ObjectPtr(const ObjectPtr<T>& other) { assign(other); }
166 
167  // Move ctor
168  ObjectPtr(ObjectPtr<T>&& other) { move(other); }
169 
170  // Assignment operator
171  ObjectPtr<T>& operator=(const ObjectPtr<T>& other) { assign(other); return *this; }
172 
173  // Move assignment operator
174  ObjectPtr<T>& operator=(ObjectPtr<T>&& other) { move(other); return *this; }
175 
176  // Raw object pointer
177  T* get() const { return static_cast<T*>(mPtr); }
178 
179  // Raw object pointer
180  T* get() { return static_cast<T*>(mPtr); }
181 
183 
184  // Regular ctor taking different type
185  template<typename OTHER>
186  ObjectPtr(const ObjectPtr<OTHER>& other) { assign(other); }
187 
188  // Regular move ctor taking different type
189  template<typename OTHER>
190  ObjectPtr(ObjectPtr<OTHER>&& other) { move(other); }
191 
192  // Assignment operator taking different type
193  template<typename OTHER>
194  ObjectPtr<T>& operator=(const ObjectPtr<OTHER>& other) { assign(other); return *this; }
195 
196  // Move assignment operator taking different type
197  template<typename OTHER>
198  ObjectPtr<T>& operator=(ObjectPtr<OTHER>&& other) { move(other); return *this; }
199 
201 
202  const T& operator*() const { assert(mPtr != nullptr); return *static_cast<T*>(mPtr); }
203 
204  T& operator*() { assert(mPtr != nullptr); return *static_cast<T*>(mPtr); }
205 
206  T* operator->() const { assert(mPtr != nullptr); return static_cast<T*>(mPtr); }
207 
208  T* operator->() { assert(mPtr != nullptr); return static_cast<T*>(mPtr); }
209 
210  bool operator==(const ObjectPtr<T>& other) const { return mPtr == other.mPtr; }
211 
212  template<typename OTHER>
213  bool operator==(const ObjectPtr<OTHER>& other) const { return mPtr == other.mPtr; }
214 
215  template<typename OTHER>
216  bool operator==(const OTHER* ptr) const { return mPtr == ptr; }
217 
218  bool operator==(std::nullptr_t) const { return mPtr == nullptr; }
219 
220  bool operator!=(const ObjectPtr<T>& other) const { return mPtr != other.mPtr; }
221 
222  template<typename OTHER>
223  bool operator!=(const ObjectPtr<OTHER>& other) const { return mPtr != other.mPtr; }
224 
225  template<typename OTHER>
226  bool operator!=(const OTHER* ptr) const { return mPtr != ptr; }
227 
228  bool operator!=(std::nullptr_t) const { return mPtr != nullptr; }
229 
230  bool operator<(const ObjectPtr<T>& other) const { return mPtr < other.mPtr; }
231 
232  bool operator>(const ObjectPtr<T>& other) const { return mPtr > other.mPtr; }
233 
234  bool operator<=(const ObjectPtr<T>& other) const { return mPtr <= other.mPtr; }
235 
236  bool operator>=(const ObjectPtr<T>& other) const { return mPtr >= other.mPtr; }
237 
238  private:
242  template<typename OTHER>
243  void move(ObjectPtr<OTHER>& other);
244 
248  template<typename OTHER>
249  void assign(const ObjectPtr<OTHER>& other);
250  };
251 
252 
254  // Template Definitions
256 
257  template<class OBJECTSBYIDMAP>
258  void ObjectPtrManager::patchPointers(OBJECTSBYIDMAP& newTargetObjects)
259  {
260  for (ObjectPtrBase* ptr : mObjectPointers)
261  {
262  rtti::Object* target = ptr->get();
263  if (target == nullptr)
264  continue;
265 
266  std::string& target_id = target->mID;
267  typename OBJECTSBYIDMAP::iterator new_target = newTargetObjects.find(target_id);
268  if (new_target != newTargetObjects.end())
269  ptr->set(&*(new_target->second));
270  }
271  }
272 
273 
274  template<typename T>
276  {
277  if (mPtr != nullptr)
278  {
279  mPtr->decrementObjectPtrRefCount();
280  }
281  ObjectPtrManager::get().remove(*this);
282  }
283 
284  template<typename T>
286  {
287  if (mPtr != nullptr)
288  {
289  ObjectPtrManager::get().add(*this);
290  mPtr->incrementObjectPtrRefCount();
291  }
292  }
293 
294  template<typename T>
295  template<typename OTHER>
297  {
298  assign(other);
299  if (other.mPtr != nullptr)
300  {
301  other.mPtr->decrementObjectPtrRefCount();
302  other.mPtr = nullptr;
303  }
304  }
305 
306  template<typename T>
307  template<typename OTHER>
308  void nap::rtti::ObjectPtr<T>::assign(const ObjectPtr<OTHER>& other)
309  {
310  if (mPtr == nullptr && other.mPtr != nullptr)
311  ObjectPtrManager::get().add(*this);
312 
313  if (other.mPtr != mPtr)
314  {
315  if (mPtr != nullptr)
316  mPtr->decrementObjectPtrRefCount();
317 
318  mPtr = static_cast<T*>(other.get());
319 
320  if (mPtr != nullptr)
321  mPtr->incrementObjectPtrRefCount();
322  }
323 
324  if (mPtr == nullptr)
325  ObjectPtrManager::get().remove(*this);
326  }
327 
328  }
329 }
330 
331 
335 namespace rttr
336 {
337  template<typename T>
338  struct wrapper_mapper<nap::rtti::ObjectPtr<T>>
339  {
340  using wrapped_type = T*;
341  using type = nap::rtti::ObjectPtr<T>;
342  inline static wrapped_type get(const type& obj) { return obj.get(); }
343  inline static type create(const wrapped_type& value) { return nap::rtti::ObjectPtr<T>(value); }
344  };
345 }
nap::rtti::ObjectPtrManager::patchPointers
void patchPointers(OBJECTSBYIDMAP &newTargetObjects)
Definition: objectptr.h:258
nap::rtti::Object::mID
std::string mID
Property: 'mID' unique name of the object. Used as an identifier by the system.
Definition: object.h:82
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr()=default
nap::rtti::ObjectPtrManager::ObjectPtrSet
std::unordered_set< ObjectPtrBase * > ObjectPtrSet
Definition: objectptr.h:92
nap::rtti::ObjectPtr::operator<=
bool operator<=(const ObjectPtr< T > &other) const
Definition: objectptr.h:234
nap::rtti::ObjectPtrBase::getWrappedType
rttr::type getWrappedType() const
Definition: objectptr.h:32
nap::rtti::ObjectPtr::operator*
const T & operator*() const
Definition: objectptr.h:202
nap::rtti::ObjectPtr::operator==
bool operator==(std::nullptr_t) const
Definition: objectptr.h:218
nap::rtti::ObjectPtr::operator->
T * operator->() const
Definition: objectptr.h:206
nap::rtti::ObjectPtr::operator!=
bool operator!=(const OTHER *ptr) const
Definition: objectptr.h:226
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(const ObjectPtr< T > &other)
Definition: objectptr.h:165
nap::rtti::ObjectPtr::operator<
bool operator<(const ObjectPtr< T > &other) const
Definition: objectptr.h:230
nap::rtti::ObjectPtr
Definition: objectptr.h:150
nap::rtti::Object
Definition: object.h:30
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(const ObjectPtr< OTHER > &other)
Definition: objectptr.h:194
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(ObjectPtr< OTHER > &&other)
Definition: objectptr.h:198
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(const ObjectPtr< T > &other)
Definition: objectptr.h:171
nap::rtti::ObjectPtr::operator==
bool operator==(const ObjectPtr< OTHER > &other) const
Definition: objectptr.h:213
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(ObjectPtr< T > &&other)
Definition: objectptr.h:174
nap::rtti::ObjectPtr::operator!=
bool operator!=(const ObjectPtr< T > &other) const
Definition: objectptr.h:220
nap::rtti::ObjectPtr::operator>
bool operator>(const ObjectPtr< T > &other) const
Definition: objectptr.h:232
nap::rtti::ObjectPtr::operator!=
bool operator!=(const ObjectPtr< OTHER > &other) const
Definition: objectptr.h:223
nap::rtti::ObjectPtrManager::resetPointers
void resetPointers(const rtti::Object &targetObject)
Definition: objectptr.h:111
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(ObjectPtr< T > &&other)
Definition: objectptr.h:168
nap::rtti::ObjectPtr::~ObjectPtr
virtual ~ObjectPtr() override
Definition: objectptr.h:275
nap::rtti::ObjectPtrManager
Definition: objectptr.h:89
nap::rtti::ObjectPtr::operator->
T * operator->()
Definition: objectptr.h:208
nap::rtti::ObjectPtr::get
T * get() const
Definition: objectptr.h:177
nap::rtti::ObjectPtrManager::get
static ObjectPtrManager & get()
nap::rtti::ObjectPtr::operator*
T & operator*()
Definition: objectptr.h:204
nap
Definition: templateapp.h:17
nap::rtti::ObjectPtr::operator==
bool operator==(const ObjectPtr< T > &other) const
Definition: objectptr.h:210
nap::rtti::ObjectPtr::operator!=
bool operator!=(std::nullptr_t) const
Definition: objectptr.h:228
nap::rtti::ObjectPtr::get
T * get()
Definition: objectptr.h:180
nap::rtti::ObjectPtr::operator==
bool operator==(const OTHER *ptr) const
Definition: objectptr.h:216
nap::rtti::ObjectPtr::operator>=
bool operator>=(const ObjectPtr< T > &other) const
Definition: objectptr.h:236
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(const ObjectPtr< OTHER > &other)
Definition: objectptr.h:186
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(ObjectPtr< OTHER > &&other)
Definition: objectptr.h:190
nap::rtti::ObjectPtrBase
Definition: objectptr.h:23