NVIDIA NvNeural SDK  2022.2
GPU inference framework for NVIDIA Nsight Deep Learning Designer
RefPtr.h
Go to the documentation of this file.
1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 
27 
28 #ifndef NVNEURAL_REFPTR_H
29 #define NVNEURAL_REFPTR_H
30 
31 #include <nvneural/CoreTypes.h>
32 
33 #include <type_traits>
34 #include <utility>
35 
36 namespace nvneural {
37 
44 template<typename TObject>
45 class RefPtr
46 {
47  // Sanity-check the template parameter
48  static_assert(std::is_convertible<TObject*, const IRefObject*>::value, "Object must inherit from nvneural::IRefObject");
49 
50 public:
52  RefPtr() noexcept
53  : m_pObject{nullptr}
54  {
55  }
56 
65  static RefPtr fromPointer(TObject* pObject)
66  {
67  RefPtr pResult;
68  pResult.m_pObject = pObject;
69  pResult.safeAddRef();
70  return pResult;
71  }
72 
79  static RefPtr fromPointerNoAddRef(TObject* pObject)
80  {
81  RefPtr pResult;
82  pResult.m_pObject = pObject;
83  return pResult;
84  }
85 
91  RefPtr(const RefPtr& copyFrom) noexcept
92  : m_pObject{copyFrom.m_pObject}
93  {
94  safeAddRef();
95  }
96 
104  RefPtr(RefPtr&& moveFrom) noexcept
105  : m_pObject{nullptr}
106  {
107  std::swap(m_pObject, moveFrom.m_pObject);
108 
109  // Object maintains current reference count;
110  // old object released when moveFrom is destroyed
111  }
112 
115  {
116  safeRelease();
117  }
118 
125  RefPtr& operator =(const RefPtr& copyFrom) noexcept
126  {
127  const auto pOldObject = std::exchange(m_pObject, copyFrom.m_pObject);
128  safeAddRef();
129  if (pOldObject)
130  {
131  pOldObject->release();
132  }
133  return *this;
134  }
135 
142  RefPtr& operator =(RefPtr&& moveFrom) noexcept
143  {
144  std::swap(m_pObject, moveFrom.m_pObject);
145 
146  // Object maintains current reference count;
147  // old object released when moveFrom is destroyed
148 
149  return *this;
150  }
151 
155  RefPtr& operator =(std::nullptr_t) noexcept
156  {
157  safeRelease();
158 
159  m_pObject = nullptr;
160 
161  return *this;
162  }
163 
171  TObject* get() const noexcept
172  {
173  return m_pObject;
174  }
175 
186  TObject* detach() noexcept
187  {
188  return std::exchange(m_pObject, nullptr);
189  }
190 
196  TObject& operator *() const noexcept
197  {
198  return *m_pObject;
199  }
200 
206  TObject* operator ->() const noexcept
207  {
208  return m_pObject;
209  }
210 
212  explicit operator bool() const noexcept
213  {
214  return m_pObject != nullptr;
215  }
216 
220  template<typename TDestinationObject>
222  {
223  if (!m_pObject)
224  {
226  }
227 
228  const auto destinationInterface = InterfaceOf<TDestinationObject>::value;
229  const auto pRawObject = m_pObject->queryInterface(destinationInterface);
230  return RefPtr<TDestinationObject>::fromPointerNoAddRef(static_cast<TDestinationObject*>(pRawObject));
231  }
232 
234  bool operator ==(const RefPtr<TObject>& other) const noexcept
235  {
236  return m_pObject == other.m_pObject;
237  }
238 
240  bool operator ==(const TObject* pOther) const noexcept
241  {
242  return m_pObject == pOther;
243  }
244 
246  bool operator !=(const RefPtr<TObject>& other) const noexcept
247  {
248  return m_pObject != other.m_pObject;
249  }
250 
252  bool operator !=(const TObject* pOther) const noexcept
253  {
254  return m_pObject != pOther;
255  }
256 
271  {
272  friend class RefPtr;
273 
274  private:
275  RefPtr& m_parent;
276 
278  explicit OutputWrapper(RefPtr& parent)
279  : m_parent(parent)
280  {
281  }
282 
283  public:
287  {
288  // Force another queryInterface call to ensure the interface is what we think it is
289  m_parent = m_parent.as<TObject>();
290  }
291 
293  operator TObject**()
294  {
295  return &m_parent.m_pObject;
296  }
297  };
298 
301  {
302  friend class RefPtr;
303 
304  private:
305  RefPtr& m_parent;
306  IRefObject* m_pBuffer;
307 
309  explicit GenericOutputWrapper(RefPtr& parent)
310  : m_parent(parent)
311  , m_pBuffer(nullptr)
312  {
313  }
314 
315  public:
318  {
319  m_parent = RefPtr<IRefObject>::fromPointerNoAddRef(m_pBuffer).as<TObject>();
320  }
321 
323  operator IRefObject**()
324  {
325  return &m_pBuffer;
326  }
327  };
328 
329  friend class OutputWrapper;
330  friend class GenericOutputWrapper;
331 
337  OutputWrapper put() & noexcept
338  {
339  safeRelease();
340  m_pObject = nullptr;
341  return OutputWrapper(*this);
342  }
343 
350  {
351  safeRelease();
352  m_pObject = nullptr;
353  return GenericOutputWrapper(*this);
354  }
355 
356 private:
358  TObject* m_pObject;
359 
363  void safeAddRef() const noexcept
364  {
365  if (m_pObject)
366  {
367  m_pObject->addRef();
368  }
369  }
370 
374  void safeRelease() const noexcept
375  {
376  if (m_pObject)
377  {
378  m_pObject->release();
379  }
380  }
381 };
382 
392 template<typename TObject, typename TIntermediate = void, typename... TArguments>
393 inline RefPtr<IRefObject> make_refobject(TArguments&&... args) noexcept
394 {
395  try
396  {
397  return RefPtr<IRefObject>::fromPointerNoAddRef(static_cast<IRefObject*>(static_cast<TIntermediate*>(new TObject(std::forward<TArguments>(args)...))));
398  }
399  catch (...)
400  {
401  return RefPtr<IRefObject>();
402  }
403 }
404 
405 } // namespace nvneural
406 
407 namespace std
408 {
412  template<typename TObject> struct hash<nvneural::RefPtr<TObject>>
413  {
415  std::size_t operator ()(const nvneural::RefPtr<TObject>& pObject) const noexcept
416  {
417  // Our hash algorithm: Reinterpret the underlying pointer as a size_t.
418  //
419  // Requirements of a std::hash function:
420  //
421  // 1: Takes a single parameter of the appropriate type. (obvious)
422  // 2: Returns a size_t that represents the value of the parameter.
423  // (The size_t type is equivalent to uintptr_t on our supported platforms,
424  // so we can convert a pointer to size_t without losing bits.)
425  // 3: Does not throw. (RefPtr<T>::get is noexcept, so we're good here.)
426  // 4: Hash of equal values is equal. (RefPtr<T> objects are equal if their
427  // underlying pointers are equal, so we preserve that relationship.)
428  // 5: Probability of unequal values hashing equally should be low. (Our
429  // hash is 1:1 with all possible values, so P(collision) is zero.)
430  return reinterpret_cast<std::size_t>(pObject.get());
431  }
432  };
433 } // namespace std
434 
435 #endif // NVNEURAL_REFPTR_H
Fundamental NvNeural data types are declared here.
RefPtr< IRefObject > make_refobject(TArguments &&... args) noexcept
Creates a RefPtr pointing to a new object instance, forwarding constructor arguments.
Definition: RefPtr.h:393
Base class for all objects, similar to COM's IUnknown.
Definition: CoreTypes.h:343
Version of OutputWrapper that presents a generic IRefObject** instead.
Definition: RefPtr.h:301
~GenericOutputWrapper()
Reassigns to the original RefPtr after a queryInterface.
Definition: RefPtr.h:317
Details type that allows version-safe use of out-pointer parameters without converting through an int...
Definition: RefPtr.h:271
~OutputWrapper()
After the pointer-consuming expression has been evaluated, ensure the pointer returned by the externa...
Definition: RefPtr.h:286
Intrusive pointer using IRefObject's reference counting system.
Definition: RefPtr.h:46
bool operator!=(const RefPtr< TObject > &other) const noexcept
Compares reference pointers for underlying inequality.
Definition: RefPtr.h:246
TObject * get() const noexcept
Returns the pointed-to object.
Definition: RefPtr.h:171
RefPtr(const RefPtr &copyFrom) noexcept
Initializes a new RefPtr pointing to a preexisting RefPtr-tracked object.
Definition: RefPtr.h:91
bool operator==(const RefPtr< TObject > &other) const noexcept
Compares reference pointers for underlying equality.
Definition: RefPtr.h:234
static RefPtr fromPointerNoAddRef(TObject *pObject)
Initializes a RefPtr pointing to a specific object.
Definition: RefPtr.h:79
RefPtr(RefPtr &&moveFrom) noexcept
Initializes a new RefPtr pointing to a preexisting RefPtr-tracked object.
Definition: RefPtr.h:104
OutputWrapper put() &noexcept
Returns an expression proxy that acts like a TObject** for receiving new pointers.
Definition: RefPtr.h:337
TObject * operator->() const noexcept
Dereferences this RefPtr.
Definition: RefPtr.h:206
RefPtr< TDestinationObject > as() const noexcept
Creates a new reference to the object using the specified interface.
Definition: RefPtr.h:221
~RefPtr()
Releases the reference to the tracked object.
Definition: RefPtr.h:114
static RefPtr fromPointer(TObject *pObject)
Initializes a RefPtr pointing to a specific object.
Definition: RefPtr.h:65
GenericOutputWrapper put_refobject() &noexcept
Returns an expression proxy that acts like an IRefObject** for receiving new pointers.
Definition: RefPtr.h:349
TObject * detach() noexcept
Returns the pointed-to object and releases ownership over its reference.
Definition: RefPtr.h:186
TObject & operator*() const noexcept
Dereferences this RefPtr.
Definition: RefPtr.h:196
RefPtr() noexcept
Initializes a RefPtr pointing to nullptr.
Definition: RefPtr.h:52
RefPtr & operator=(const RefPtr &copyFrom) noexcept
Reassigns this RefPtr to point to a new object.
Definition: RefPtr.h:125
Helper template to aid retrieval of interface IDs.
Definition: CoreTypes.h:403