Math API nvidia_logo_transpbg.gif Up
mi::base::Handle<Interface> Class Template Reference

Handle class template for interfaces, automatizing the lifetime control via reference counting. More...

#include <handle.h>

Public Types

typedef Handle<Interface> Self
 Own type. More...
 
typedef Interface Interface_type
 Type of the underlying interface. More...
 
typedef Interface value_type
 Type of the underlying interface. More...
 
typedef Difference difference_type
 Difference type (signed integral type to hold pointer differences). More...
 
typedef Interface * pointer
 Mutable-pointer type to underlying interface. More...
 
typedef Interface & reference
 Mutable-reference type to underlying interface. More...
 
typedef bool(Handle::* bool_conversion_support) () const
 Helper typedef. More...
 

Public Member Functions

 Handle ()
 Default constructor, initializes handle to hold an invalid interface. More...
 
 Handle (Interface *ptr)
 Constructor from interface pointer, takes ownership of interface. More...
 
 Handle (Interface *ptr, Dup_interface)
 Constructor from interface pointer, does not take ownership of interface but duplicates it. More...
 
 Handle (const Self &other)
 Copy constructor, increments reference count if interface is valid. More...
 
template<class Interface2>
 Handle (const Handle<Interface2> &other)
 Copy constructor template which allows the construction from assignment compatible interface pointers, increments reference count if interface is valid. More...
 
 Handle (Self &&other) noexcept
 Move constructor. More...
 
template<class Interface2>
 Handle (Handle<Interface2> &&other) noexcept
 Converting move constructor. More...
 
void swap (Self &other)
 Swap two interfaces. More...
 
Selfoperator= (const Self &other)
 Assignment operator, releases old interface and increments reference count of the new interface if interface is valid. More...
 
template<class Interface2>
Selfoperator= (const Handle<Interface2> &other)
 Assignment operator template, releases old interface and increments reference count of the new interface if interface is valid. More...
 
Selfoperator= (Self &&other) noexcept
 Move assignment operator, releases old interface. More...
 
template<class Interface2>
Selfoperator= (Handle<Interface2> &&other) noexcept
 Converting move assignment operator, releases old interface. More...
 
Selfoperator= (Interface *ptr)
 Assignment operator from interface pointer, releases old interface and assigns new interface ptr, takes ownership of interface. More...
 
void reset ()
 Releases the current interface, decrementing the reference count. More...
 
 ~Handle ()
 Destructor, releases the interface if it is valid, which decrements the reference count, and triggers thus the deletion of the interface implementation once the reference count reaches zero. More...
 
bool is_valid_interface () const
 Returns true if the interface is valid. More...
 
Interface * get () const
 Access to the interface. Returns 0 for an invalid interface. More...
 
Interface * extract ()
 Extracts the interface and releases the handle. More...
 
Interface & operator* () const
 The dereference operator accesses the interface. More...
 
Interface * operator-> () const
 The arrow operator accesses the interface. More...
 
template<class New_interface>
Handle<New_interface> get_interface () const
 Returns a new handle for a possibly different interface type, similar to a dynamic cast, but not necessarily restricted to derived interfaces, but also for otherwise related interfaces. More...
 
 operator bool_conversion_support () const
 Helper function for the conversion of a Handle<Interface> to a bool. More...
 

Detailed Description

template<class Interface>
class mi::base::Handle<Interface>

Handle class template for interfaces, automatizing the lifetime control via reference counting.

The Handle class is smart-pointer class that handles the reference counting of interface classes automatically. A handle stores internally a pointer to the underlying interface class.

Template parameter:

  • Interface: an interface class, i.e., either the mi::base::IInterface class itself or a class derived from it.
Note
The Handle class is const correct: Use Handle<const I> for a const pointer to an interface class I and Handle<I> for a mutable pointer to an interface class I.

The Handle class has two constructors which differ in the way they handle ownership of the interface pointer they are constructed from (actually, there is a third constructor, the default constructor, which constructs an invalid handle). In the first form mi::base::Handle<I>(I*) the Handle instance takes ownership of the interface. In the second form mi::base::Handle<I>(I*,Dup_interface) it does not take ownership of the interface, but duplicates it.

The following two examples, based on the neuraylib API, illustrate the use of both constructors. The first example demonstrates the prevailing use case where you want to locally store the interface pointer returned from an API function for subsequent usage. In this case you should use the first form of the constructor which takes ownership of the interface.

mi::base::Handle<mi::neuraylib::INeuray> neuray( mi_neuray_factory());
neuray->start( true);
Handle class template for interfaces, automatizing the lifetime control via reference counting.
Definition: handle.h:113

On the other hand, assume that you want to store a pointer to an interface whose lifetime you do not control. This typically happens when a pointer is passed as parameter to a function. By convention such pointers are owned by the function caller.

void foo( mi::base::IInterface* interface)
{
// do something with handle
}
mi::base::IInterface* interface = ...
foo( interface);
// do more things with interface
The basic extensible interface.
Definition: iinterface.h:103
static const Dup_interface DUP_INTERFACE
Symbolic constant to trigger a special constructor in the Handle class.
Definition: handle.h:37

If you had not used the second form of the handle constructor in this example, the handle destructor would have decremented the reference counter of interface to 0 at the end of foo(). Therefore, the corresponding interface would have been destroyed and the interface pointer would be invalid after the foo() call.

In contrast, the second form of the handle constructor does not take ownership of the interface pointer, but increments the reference count once more. Consequently, when the handle is destroyed, the reference count does not drop to 0.

Note that this use case often shows up when you store a pointer passed in via a member function as a class member.

Include File:
#include <mi/base/handle.h>
See also
make_handle() and make_handle_dup() for creating a typed handle from a typed interface pointer