MDL SDK API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
handle.h
Go to the documentation of this file.
1 /***************************************************************************************************
2  * Copyright 2022 NVIDIA Corporation. All rights reserved.
3  **************************************************************************************************/
6 
7 #ifndef MI_BASE_HANDLE_H
8 #define MI_BASE_HANDLE_H
9 
10 #include <mi/base/assert.h>
11 #include <mi/base/config.h> // for MI_CXX_FEATURE_RVALUE_REFERENCES
12 #include <mi/base/iinterface.h>
13 
14 #ifdef __cpp_variadic_templates
15 #include <utility>
16 #endif
17 
18 
19 namespace mi {
20 namespace base {
21 
26 // Helper type to define Dup_interface
27 struct Dup_interface_helper {};
28 
32 typedef const Dup_interface_helper* Dup_interface;
33 
37 static const Dup_interface DUP_INTERFACE = 0;
38 
111 template <class Interface>
112 class Handle
113 {
114 public:
117 
119  typedef Interface Interface_type;
120 
121  // STL iterator inspired typedef names
122 
124  typedef Interface value_type;
125 
128 
130  typedef Interface* pointer;
131 
133  typedef Interface& reference;
134 
135 private:
136  template <typename I2> friend class Handle;
137 
138  // Pointer to underlying interface, can be \c NULL
139  Interface* m_iptr;
140 
141 public:
143  Handle() : m_iptr( 0) { }
144 
150  explicit Handle( Interface* ptr) : m_iptr( ptr) { }
151 
159  Handle( Interface* ptr, Dup_interface)
160  : m_iptr( ptr)
161  {
162  if( m_iptr)
163  m_iptr->retain();
164  }
165 
167  Handle( const Self& other)
168  : m_iptr( other.m_iptr)
169  {
170  if( m_iptr)
171  m_iptr->retain();
172  }
173 
180  template <class Interface2>
181  Handle( const Handle<Interface2>& other)
182  : m_iptr( other.get())
183  {
184  if( m_iptr)
185  m_iptr->retain();
186  }
187 
188 #ifdef MI_CXX_FEATURE_RVALUE_REFERENCES
189  Handle( Self&& other)
191  : m_iptr( other.m_iptr)
192  {
193  other.m_iptr = 0;
194  }
195 
197  template <class Interface2>
199  : m_iptr( other.m_iptr)
200  {
201  other.m_iptr = 0;
202  }
203 #endif
204 
206  void swap( Self& other)
207  {
208  Interface* tmp_iptr = m_iptr;
209  m_iptr = other.m_iptr;
210  other.m_iptr = tmp_iptr;
211  }
212 
215  Self& operator=( const Self& other)
216  {
217  Self( other).swap( *this);
218  return *this;
219  }
220 
228  template <class Interface2>
230  {
231  Self( other).swap( *this);
232  return *this;
233  }
234 
235 #ifdef MI_CXX_FEATURE_RVALUE_REFERENCES
236  Self& operator=( Self&& other)
238  {
239  if( this != &other) {
240  if( m_iptr)
241  m_iptr->release();
242  m_iptr = other.m_iptr;
243  other.m_iptr = 0;
244  }
245  return *this;
246  }
247 
249  template <class Interface2>
251  {
252  if( m_iptr)
253  m_iptr->release();
254  m_iptr = other.m_iptr;
255  other.m_iptr = 0;
256 
257  return *this;
258  }
259 #endif
260 
266  Self& operator=( Interface* ptr)
267  {
268  Self( ptr).swap( *this);
269  return *this;
270  }
271 
273  void reset()
274  {
275  if( m_iptr) {
276  m_iptr->release();
277  m_iptr = 0;
278  }
279  }
280 
285  {
286  if( m_iptr)
287  m_iptr->release();
288  }
289 
291  bool is_valid_interface() const { return m_iptr != 0; }
292 
294  Interface* get() const { return m_iptr; }
295 
299  Interface* extract()
300  {
301  Interface* ptr = m_iptr;
302  m_iptr = 0;
303  return ptr;
304  }
305 
306 #ifdef __cpp_variadic_templates
307  template <typename... T>
309  Self& emplace(T&&... args)
310  {
311  return emplace<Interface>(std::forward<T>(args)...);
312  }
313 
319  template <typename Impl, typename... T>
320  Self& emplace(T&&... args)
321  {
322  reset();
323  m_iptr = new Impl(std::forward<T>(args)...);
324  return *this;
325  }
326 #endif
327 
331  Interface& operator*() const
332  {
333  mi_base_assert_msg( is_valid_interface(), "precondition");
334  return *m_iptr;
335  }
336 
340  Interface* operator->() const
341  {
342  mi_base_assert_msg( is_valid_interface(), "precondition");
343  return m_iptr;
344  }
345 
351  template <class New_interface>
353  {
354  if( !is_valid_interface())
355  return Handle<New_interface>( 0);
356  return Handle<New_interface>( static_cast< New_interface*>(
357  m_iptr->get_interface( typename New_interface::IID())));
358  }
359 
364  typedef bool (Handle::*bool_conversion_support)() const;
365 
378  operator bool_conversion_support() const
379  {
381  }
382 
384  friend bool operator==( const Handle<Interface>& lhs, const Interface* rhs)
385  {
386  return lhs.get() == rhs;
387  }
388 
390  friend bool operator==( const Interface* lhs, const Handle<Interface>& rhs)
391  {
392  return lhs == rhs.get();
393  }
394 
396  friend bool operator!=( const Handle<Interface>& lhs, const Interface* rhs)
397  {
398  return !( lhs == rhs);
399  }
400 
402  friend bool operator!=( const Interface* lhs, const Handle<Interface>& rhs) {
403  return !( lhs == rhs);
404  }
405 };
406 
408 template <class Interface1, class Interface2>
409 inline bool operator==( const Handle<Interface1>& lhs, const Handle<Interface2>& rhs)
410 {
411  return lhs.get() == rhs.get();
412 }
413 
415 template <class Interface1, class Interface2>
416 inline bool operator!=( const Handle<Interface1>& lhs, const Handle<Interface2>& rhs)
417 {
418  return !( lhs == rhs);
419 }
420 
426 template <class Interface>
427 inline Handle<Interface> make_handle( Interface* iptr)
428 {
429  return Handle<Interface>( iptr);
430 }
431 
437 template <class Interface>
438 inline Handle<Interface> make_handle_dup( Interface* iptr)
439 {
440  return Handle<Interface>( iptr, DUP_INTERFACE);
441 }
442 
443 #ifdef __cpp_variadic_templates
444 template <typename Impl, typename... T>
449 inline Handle<Impl> construct_handle(T&&... args)
450 {
451  return Handle<Impl>{new Impl(std::forward<T>(args)...)};
452 }
453 
454 #endif
455 
456  // end group mi_base_iinterface
458 
459 } // namespace base
460 } // namespace mi
461 
462 #endif // MI_BASE_HANDLE_H