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 #ifdef NAP_ENABLE_PYTHON
15  #include <pybind11/cast.h>
16 #endif
17 
18 namespace nap
19 {
20  namespace rtti
21  {
27  class NAPAPI ObjectPtrBase
28  {
29  RTTI_ENABLE()
30  public:
31  virtual ~ObjectPtrBase() = default;
32 
36  rttr::type getWrappedType() const { return mPtr->get_type(); }
37 
38  private:
39  ObjectPtrBase() = default;
40 
45  mPtr(ptr) { }
46 
50  rtti::Object* get() { return mPtr; }
51 
55  const rtti::Object* get() const { return mPtr; }
56 
57  private:
61  void set(rtti::Object* ptr)
62  {
63  if (mPtr != nullptr)
64  mPtr->decrementObjectPtrRefCount();
65 
66  mPtr = ptr;
67 
68  if (mPtr != nullptr)
69  mPtr->incrementObjectPtrRefCount();
70  }
71  private:
72  template<class T> friend class ObjectPtr;
73  friend class ObjectPtrManager;
74  rtti::Object* mPtr = nullptr;
75  };
76 
77 
93  class NAPAPI ObjectPtrManager
94  {
95  public:
96  typedef std::unordered_set<ObjectPtrBase*> ObjectPtrSet;
97 
101  static ObjectPtrManager& get();
102 
108  template<class OBJECTSBYIDMAP>
109  void patchPointers(OBJECTSBYIDMAP& newTargetObjects);
110 
115  void resetPointers(const rtti::Object& targetObject)
116  {
117  for (ObjectPtrBase* ptr : mObjectPointers)
118  {
119  if (ptr->get() == &targetObject)
120  ptr->set(nullptr);
121  }
122  }
123 
124  private:
125  template<class T> friend class ObjectPtr;
126 
130  void add(ObjectPtrBase& ptr) { mObjectPointers.insert(&ptr); }
131 
135  void remove(ObjectPtrBase& ptr) { mObjectPointers.erase(&ptr); }
136 
137  ObjectPtrSet mObjectPointers;
138  };
139 
153  template<typename T>
154  class ObjectPtr : public ObjectPtrBase
155  {
156  RTTI_ENABLE(ObjectPtrBase)
157 
158  public:
159  // Default constructor
160  ObjectPtr() = default;
161 
162  // Dtor
163  virtual ~ObjectPtr() override;
164 
165  // Regular ptr Ctor
166  ObjectPtr(T* ptr);
167 
168  // Copy ctor
169  ObjectPtr(const ObjectPtr<T>& other) { assign(other); }
170 
171  // Move ctor
172  ObjectPtr(ObjectPtr<T>&& other) { move(other); }
173 
174  // Assignment operator
175  ObjectPtr<T>& operator=(const ObjectPtr<T>& other) { assign(other); return *this; }
176 
177  // Move assignment operator
178  ObjectPtr<T>& operator=(ObjectPtr<T>&& other) { move(other); return *this; }
179 
180  // Raw object pointer
181  T* get() const { return static_cast<T*>(mPtr); }
182 
183  // Raw object pointer
184  T* get() { return static_cast<T*>(mPtr); }
185 
187 
188  // Regular ctor taking different type
189  template<typename OTHER>
190  ObjectPtr(const ObjectPtr<OTHER>& other) { assign(other); }
191 
192  // Regular move ctor taking different type
193  template<typename OTHER>
194  ObjectPtr(ObjectPtr<OTHER>&& other) { move(other); }
195 
196  // Assignment operator taking different type
197  template<typename OTHER>
198  ObjectPtr<T>& operator=(const ObjectPtr<OTHER>& other) { assign(other); return *this; }
199 
200  // Move assignment operator taking different type
201  template<typename OTHER>
202  ObjectPtr<T>& operator=(ObjectPtr<OTHER>&& other) { move(other); return *this; }
203 
205 
206  const 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  T* operator->() const { assert(mPtr != nullptr); return static_cast<T*>(mPtr); }
211 
212  T* operator->() { assert(mPtr != nullptr); return static_cast<T*>(mPtr); }
213 
214  bool operator==(const ObjectPtr<T>& other) const { return mPtr == other.mPtr; }
215 
216  template<typename OTHER>
217  bool operator==(const ObjectPtr<OTHER>& other) const { return mPtr == other.mPtr; }
218 
219  template<typename OTHER>
220  bool operator==(const OTHER* ptr) const { return mPtr == ptr; }
221 
222  bool operator==(std::nullptr_t) const { return mPtr == nullptr; }
223 
224  bool operator!=(const ObjectPtr<T>& other) const { return mPtr != other.mPtr; }
225 
226  template<typename OTHER>
227  bool operator!=(const ObjectPtr<OTHER>& other) const { return mPtr != other.mPtr; }
228 
229  template<typename OTHER>
230  bool operator!=(const OTHER* ptr) const { return mPtr != ptr; }
231 
232  bool operator!=(std::nullptr_t) const { return mPtr != nullptr; }
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  bool operator<=(const ObjectPtr<T>& other) const { return mPtr <= other.mPtr; }
239 
240  bool operator>=(const ObjectPtr<T>& other) const { return mPtr >= other.mPtr; }
241 
242  private:
246  template<typename OTHER>
247  void move(ObjectPtr<OTHER>& other);
248 
252  template<typename OTHER>
253  void assign(const ObjectPtr<OTHER>& other);
254  };
255 
256 
258  // Template Definitions
260 
261  template<class OBJECTSBYIDMAP>
262  void ObjectPtrManager::patchPointers(OBJECTSBYIDMAP& newTargetObjects)
263  {
264  for (ObjectPtrBase* ptr : mObjectPointers)
265  {
266  rtti::Object* target = ptr->get();
267  if (target == nullptr)
268  continue;
269 
270  std::string& target_id = target->mID;
271  typename OBJECTSBYIDMAP::iterator new_target = newTargetObjects.find(target_id);
272  if (new_target != newTargetObjects.end())
273  ptr->set(&*(new_target->second));
274  }
275  }
276 
277 
278  template<typename T>
280  {
281  if (mPtr != nullptr)
282  {
283  mPtr->decrementObjectPtrRefCount();
284  }
285  ObjectPtrManager::get().remove(*this);
286  }
287 
288  template<typename T>
290  {
291  if (mPtr != nullptr)
292  {
293  ObjectPtrManager::get().add(*this);
294  mPtr->incrementObjectPtrRefCount();
295  }
296  }
297 
298  template<typename T>
299  template<typename OTHER>
301  {
302  assign(other);
303  if (other.mPtr != nullptr)
304  {
305  other.mPtr->decrementObjectPtrRefCount();
306  other.mPtr = nullptr;
307  }
308  }
309 
310  template<typename T>
311  template<typename OTHER>
312  void nap::rtti::ObjectPtr<T>::assign(const ObjectPtr<OTHER>& other)
313  {
314  if (mPtr == nullptr && other.mPtr != nullptr)
315  ObjectPtrManager::get().add(*this);
316 
317  if (other.mPtr != mPtr)
318  {
319  if (mPtr != nullptr)
320  mPtr->decrementObjectPtrRefCount();
321 
322  mPtr = static_cast<T*>(other.get());
323 
324  if (mPtr != nullptr)
325  mPtr->incrementObjectPtrRefCount();
326  }
327 
328  if (mPtr == nullptr)
329  ObjectPtrManager::get().remove(*this);
330  }
331 
332  }
333 }
334 
335 
339 namespace rttr
340 {
341  template<typename T>
342  struct wrapper_mapper<nap::rtti::ObjectPtr<T>>
343  {
344  using wrapped_type = T*;
345  using type = nap::rtti::ObjectPtr<T>;
346  inline static wrapped_type get(const type& obj) { return obj.get(); }
347  inline static type create(const wrapped_type& value) { return nap::rtti::ObjectPtr<T>(value); }
348  };
349 }
350 
351 
388 #ifdef NAP_ENABLE_PYTHON
389 namespace pybind11
390 {
391  namespace detail
392  {
393  template <typename type>
394  struct always_construct_holder<nap::rtti::ObjectPtr<type>> : always_construct_holder<void, true>
395  {
396  };
397 
398  template <typename type> class type_caster<nap::rtti::ObjectPtr<type>> : public copyable_holder_caster<type, nap::rtti::ObjectPtr<type>>
399  {
400  public:
401  static handle cast(const nap::rtti::ObjectPtr<type>& src, return_value_policy, handle)
402  {
403  const auto *ptr = src.get();
404 
405  auto st = copyable_holder_caster<type, nap::rtti::ObjectPtr<type>>::src_and_type(ptr);
406 
407  return type_caster_generic::cast(
408  st.first, return_value_policy::reference, {}, st.second,
409  nullptr, nullptr, nullptr);
410  }
411  };
412  }
413 }
414 #endif // NAP_ENABLE_PYTHON
nap::rtti::ObjectPtrManager::patchPointers
void patchPointers(OBJECTSBYIDMAP &newTargetObjects)
Definition: objectptr.h:262
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:96
nap::rtti::ObjectPtr::operator<=
bool operator<=(const ObjectPtr< T > &other) const
Definition: objectptr.h:238
nap::rtti::ObjectPtrBase::getWrappedType
rttr::type getWrappedType() const
Definition: objectptr.h:36
nap::rtti::ObjectPtr::operator*
const T & operator*() const
Definition: objectptr.h:206
nap::rtti::ObjectPtr::operator==
bool operator==(std::nullptr_t) const
Definition: objectptr.h:222
nap::rtti::ObjectPtr::operator->
T * operator->() const
Definition: objectptr.h:210
nap::rtti::ObjectPtr::operator!=
bool operator!=(const OTHER *ptr) const
Definition: objectptr.h:230
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(const ObjectPtr< T > &other)
Definition: objectptr.h:169
nap::rtti::ObjectPtr::operator<
bool operator<(const ObjectPtr< T > &other) const
Definition: objectptr.h:234
nap::rtti::ObjectPtr
Definition: objectptr.h:154
nap::rtti::Object
Definition: object.h:30
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(const ObjectPtr< OTHER > &other)
Definition: objectptr.h:198
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(ObjectPtr< OTHER > &&other)
Definition: objectptr.h:202
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(const ObjectPtr< T > &other)
Definition: objectptr.h:175
nap::rtti::ObjectPtr::operator==
bool operator==(const ObjectPtr< OTHER > &other) const
Definition: objectptr.h:217
nap::rtti::ObjectPtr::operator=
ObjectPtr< T > & operator=(ObjectPtr< T > &&other)
Definition: objectptr.h:178
nap::rtti::ObjectPtr::operator!=
bool operator!=(const ObjectPtr< T > &other) const
Definition: objectptr.h:224
nap::rtti::ObjectPtr::operator>
bool operator>(const ObjectPtr< T > &other) const
Definition: objectptr.h:236
nap::rtti::ObjectPtr::operator!=
bool operator!=(const ObjectPtr< OTHER > &other) const
Definition: objectptr.h:227
nap::rtti::ObjectPtrManager::resetPointers
void resetPointers(const rtti::Object &targetObject)
Definition: objectptr.h:115
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(ObjectPtr< T > &&other)
Definition: objectptr.h:172
nap::rtti::ObjectPtr::~ObjectPtr
virtual ~ObjectPtr() override
Definition: objectptr.h:279
nap::rtti::ObjectPtrManager
Definition: objectptr.h:93
nap::rtti::ObjectPtr::operator->
T * operator->()
Definition: objectptr.h:212
nap::rtti::ObjectPtr::get
T * get() const
Definition: objectptr.h:181
nap::rtti::ObjectPtrManager::get
static ObjectPtrManager & get()
nap::rtti::ObjectPtr::operator*
T & operator*()
Definition: objectptr.h:208
nap
Definition: templateapp.h:17
nap::rtti::ObjectPtr::operator==
bool operator==(const ObjectPtr< T > &other) const
Definition: objectptr.h:214
nap::rtti::ObjectPtr::operator!=
bool operator!=(std::nullptr_t) const
Definition: objectptr.h:232
nap::rtti::ObjectPtr::get
T * get()
Definition: objectptr.h:184
nap::rtti::ObjectPtr::operator==
bool operator==(const OTHER *ptr) const
Definition: objectptr.h:220
nap::rtti::ObjectPtr::operator>=
bool operator>=(const ObjectPtr< T > &other) const
Definition: objectptr.h:240
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(const ObjectPtr< OTHER > &other)
Definition: objectptr.h:190
nap::rtti::ObjectPtr::ObjectPtr
ObjectPtr(ObjectPtr< OTHER > &&other)
Definition: objectptr.h:194
nap::rtti::ObjectPtrBase
Definition: objectptr.h:27