handle.h File Reference
Description
Smart-pointer handle class for interfaces, const and non-const version.
Code Example
handle.h
/***************************************************************************************************
* Copyright 2024 NVIDIA Corporation. All rights reserved.
**************************************************************************************************/
#ifndef MI_BASE_HANDLE_H
#define MI_BASE_HANDLE_H
#include <mi/base/assert.h>
#include <mi/base/config.h> // for MI_CXX_FEATURE_RVALUE_REFERENCES
#include <mi/base/iinterface.h>
#ifdef __cpp_variadic_templates
#include <utility>
#endif
namespace mi {
namespace base {
// Helper type to define Dup_interface
struct Dup_interface_helper {};
typedef const Dup_interface_helper* Dup_interface;
static const Dup_interface
DUP_INTERFACE = 0;
template <class Interface>
class Handle
{
public:
typedef Handle< Interface>
Self;
typedef Interface Interface_type;
// STL iterator inspired typedef names
typedef Interface value_type;
typedef Difference
difference_type;
typedef Interface* pointer;
typedef Interface& reference;
private:
template <typename I2> friend class Handle;
// Pointer to underlying interface, can be \c NULL
Interface* m_iptr;
public:
Handle() : m_iptr( 0) { }
explicit Handle( Interface* ptr) : m_iptr( ptr) { }
Handle( Interface* ptr, Dup_interface)
: m_iptr( ptr)
{
if( m_iptr)
m_iptr->retain();
}
Handle( const Self& other)
: m_iptr( other.m_iptr)
{
if( m_iptr)
m_iptr->retain();
}
template <class Interface2>
Handle( const Handle< Interface2>& other)
: m_iptr( other.get())
{
if( m_iptr)
m_iptr->retain();
}
#ifdef MI_CXX_FEATURE_RVALUE_REFERENCES
Handle( Self&& other) noexcept
: m_iptr( other.m_iptr)
{
other.m_iptr = 0;
}
template <class Interface2>
Handle( Handle<Interface2>&& other) noexcept
: m_iptr( other.m_iptr)
{
other.m_iptr = 0;
}
#endif
void swap( Self& other)
{
Interface* tmp_iptr = m_iptr;
m_iptr = other.m_iptr;
other.m_iptr = tmp_iptr;
}
Self& operator=( const Self& other)
{
Self( other).swap( *this);
return *this;
}
template <class Interface2>
Self& operator=( const Handle< Interface2>& other)
{
Self( other).swap( *this);
return *this;
}
#ifdef MI_CXX_FEATURE_RVALUE_REFERENCES
Self& operator=( Self&& other) noexcept
{
if( this != &other) {
if( m_iptr)
m_iptr->release();
m_iptr = other.m_iptr;
other.m_iptr = 0;
}
return *this;
}
template <class Interface2>
Self& operator=( Handle<Interface2>&& other) noexcept
{
if( m_iptr)
m_iptr->release();
m_iptr = other.m_iptr;
other.m_iptr = 0;
return *this;
}
#endif
Self& operator=( Interface* ptr)
{
Self( ptr).swap( *this);
return *this;
}
void reset()
{
if( m_iptr) {
m_iptr->release();
m_iptr = 0;
}
}
~Handle()
{
if( m_iptr)
m_iptr->release();
}
bool is_valid_interface() const { return m_iptr != 0; }
Interface* get() const { return m_iptr; }
Interface* extract()
{
Interface* ptr = m_iptr;
m_iptr = 0;
return ptr;
}
#ifdef __cpp_variadic_templates
template <typename... T>
Self& emplace(T&&... args)
{
return emplace<Interface>(std::forward<T>(args)...);
}
template <typename Impl, typename... T>
Self& emplace(T&&... args)
{
reset();
m_iptr = new Impl(std::forward<T>(args)...);
return *this;
}
#endif
Interface& operator*() const
{
mi_base_assert_msg( is_valid_interface(), "precondition");
return *m_iptr;
}
Interface* operator->() const
{
mi_base_assert_msg( is_valid_interface(), "precondition");
return m_iptr;
}
template <class New_interface>
Handle< New_interface>
get_interface() const
{
if( !is_valid_interface())
return Handle< New_interface>( 0);
return Handle< New_interface>( static_cast< New_interface*>(
m_iptr->get_interface( typename New_interface::IID())));
}
typedef bool (Handle::*bool_conversion_support)() const;
operator bool_conversion_support() const
{
return is_valid_interface() ? &Handle< Interface>::is_valid_interface : 0;
}
friend bool operator==( const Handle< Interface>& lhs, const Interface* rhs)
{
return lhs.get() == rhs;
}
friend bool operator==( const Interface* lhs, const Handle< Interface>& rhs)
{
return lhs == rhs.get();
}
friend bool operator!=( const Handle< Interface>& lhs, const Interface* rhs)
{
return !( lhs == rhs);
}
friend bool operator!=( const Interface* lhs, const Handle< Interface>& rhs) {
return !( lhs == rhs);
}
};
template <class Interface1, class Interface2>
inline bool operator==( const Handle< Interface1>& lhs, const Handle< Interface2>& rhs)
{
return lhs.get() == rhs.get();
}
template <class Interface1, class Interface2>
inline bool operator!=( const Handle< Interface1>& lhs, const Handle< Interface2>& rhs)
{
return !( lhs == rhs);
}
template <class Interface>
inline Handle< Interface>
make_handle( Interface* iptr)
{
return Handle< Interface>( iptr);
}
template <class Interface>
inline Handle< Interface>
make_handle_dup( Interface* iptr)
{
return Handle< Interface>( iptr, DUP_INTERFACE);
}
#ifdef __cpp_variadic_templates
template <typename Impl, typename... T>
inline Handle<Impl> construct_handle(T&&... args)
{
return Handle<Impl>{new Impl(std::forward<T>(args)...)};
}
#endif
// end group mi_base_iinterface
} // namespace base
} // namespace mi
#endif // MI_BASE_HANDLE_H
Namespaces
- namespace
- Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH. More...
- namespace
- Namespace for the Base API. More...
Classes
- class
- Handle class template for interfaces, automatizing the lifetime control via reference counting. More...
Typedefs
- typedef Dup_interface_helper *
- Type for a symbolic constant to trigger a special constructor in the Handle class. More...
Functions
- template< class Interface> Handle < Interface > ( Interface* iptr)
- Returns a handle that holds the interface pointer passed in as argument. More...
- template< class Interface> Handle < Interface > ( Interface* iptr)
- Converts passed-in interface pointer to a handle, without taking interface over. More...
- template< class Interface1, class Interface2>bool ( const Handle < Interface1 >& lhs, const Handle < Interface2 >& rhs)
- Returns true if the underlying interface pointers are not equal. More...
- template< class Interface1, class Interface2>bool ( const Handle < Interface1 >& lhs, const Handle < Interface2 >& rhs)
- Returns true if the underlying interface pointers are equal. More...
Variables
- static const Dup_interface
- Symbolic constant to trigger a special constructor in the Handle class. More...