My Project
unity::util::ResourcePtr< R, D > Class Template Referencefinal

Class to guarantee deallocation of arbitrary resources. More...

#include <unity/util/ResourcePtr.h>

Public Types

typedef R element_type
 
typedef D deleter_type
 

Public Member Functions

 ResourcePtr (ResourcePtr const &)=delete
 
ResourcePtroperator= (ResourcePtr const &)=delete
 
 ResourcePtr (D d)
 
 ResourcePtr (R r, D d)
 
 ResourcePtr (ResourcePtr &&r)
 
ResourcePtroperator= (ResourcePtr &&r)
 
 ~ResourcePtr () noexcept
 
void swap (ResourcePtr &other)
 
void reset (R r)
 
release ()
 
void dealloc ()
 
get () const
 
bool has_resource () const noexcept
 
 operator bool () const noexcept
 
D & get_deleter () noexcept
 
D const & get_deleter () const noexcept
 
bool operator== (ResourcePtr const &rhs) const
 Compares two instances for equality. More...
 
bool operator!= (ResourcePtr const &rhs) const
 Compares two instances for inequality. More...
 
bool operator< (ResourcePtr const &rhs) const
 Returns true if this is less than rhs. More...
 
bool operator<= (ResourcePtr const &rhs) const
 Returns true if this is less than or equal to rhs. More...
 
bool operator> (ResourcePtr const &rhs) const
 Returns true if this is greater than rhs. More...
 
bool operator>= (ResourcePtr const &rhs) const
 Returns true if this is greater than or equal to rhs. More...
 

Detailed Description

template<typename R, typename D>
class unity::util::ResourcePtr< R, D >

Class to guarantee deallocation of arbitrary resources.

ResourcePtr is a generalized resource pointer that guarantees deallocation. It is intended for arbitrary pairs of allocate/deallocate functions, such as XCreateDisplay/XDestroyDisplay.

The resource managed by this class must be default-constructible, copy-constructible, and assignable.

ResourcePtr essentially does what std::unique_ptr does, but it works with opaque types and resource allocation functions that do not return a pointer type, such as open().

ResourcePtr is thread-safe.

Note
Do not use reset() to set the resource to the "no resource allocated" state. Instead, call dealloc() to do this. ResourcePtr has no idea what a "not allocated" resource value looks like and therefore cannot test for it. If you use reset() to install a "no resource allocated" value for for the resource, the deleter will eventually be called with this value as its argument. Whether this is benign or not depends on the deleter. For example, XFree() must not be called with a nullptr argument.
Do not call get() or release() if no resource is currently allocated. Doing so throws std::logic_error.

Here is an example that shows how to use this for a glXCreateContext/GLXDestroyContext pair. The returned GLXContext is a pointer to an opaque type; std::unique_ptr cannot be used for this, even with a custom deleter, because the signatures of the allocator and deallocator do not match unique_ptr's expectations.

ResourcePtr<GLXContext, std::function<void(GLXContext)>> context =
std::bind(&glXDestroyContext, display_, std::placeholders::_1);

display_ is declared as

Display* display_;

in this case.

The deleter for the resource can return any type (including int, such as returned by XDestroyWindow()), and it must accept a single argument of the resource type (GLXContext in this example).

glXDestroyContext() expects the display pointer as the first argument so, for this example, std::bind converts the binary glXDestroyContext() function into a unary function suitable as the deleter.

Rather than mucking around with std::bind, it is often easier to use a lambda. For example:

ResourcePtr<GLXContext, std::function<void(GLXContext)>> context =
[this](GLXContext c) { this->dealloc_GLXContext(c); };

This calls a member function dealloc_GLXContext() that, in turn calls glXDestroyContext() and supplies the display parameter.

Note
Even though you can use ResourcePtr to deallocate dynamic memory, doing so is discouraged. Use std::unique_ptr instead, which is better suited to the task.

Member Typedef Documentation

template<typename R, typename D>
unity::util::ResourcePtr< R, D >::deleter_type

A function object or lvalue reference to a function or function object. The ResourcePtr calls this to deallocate the resource.

template<typename R, typename D>
unity::util::ResourcePtr< R, D >::element_type

The type of resource managed by this ResourcePtr.

Constructor & Destructor Documentation

template<typename R, typename D>
unity::util::ResourcePtr< R, D >::ResourcePtr ( ResourcePtr< R, D > const &  )
delete

Deleted

template<typename R , typename D >
unity::util::ResourcePtr< R, D >::ResourcePtr ( d)
explicit

Constructs a ResourcePtr with the specified deleter. No resource is held, so a call to has_resource() after constructing a ResourcePtr this way returns false.

template<typename R , typename D >
unity::util::ResourcePtr< R, D >::ResourcePtr ( r,
d 
)

Constructs a ResourcePtr with the specified resource and deleter. has_resource() returns true after calling this constructor.

Note
It is legal to pass a resource that represents the "not allocated" state. For example, the following code passes the value -1 to close() if the call to open() fails:
ResourcePtr<int, decltype(&::close)> fd(::open("/somefile", O_RDONLY), ::close);

When the ResourcePtr goes out of scope, this results in a call to close(-1). In this case, the call with an invalid file descriptor is harmless (but causes noise from diagnostic tools, such as valgrind). However, depending on the specific deleter, passing an invalid value to the deleter may have more serious consequences.

To avoid the problem, you can delay initialization of the ResourcePtr until you know that the resource was successfully allocated, for example:

int tmp_fd = ::open(filename.c_str(), O_RDONLY);
if (tmp_fd == -1)
{
throw FileException(filename.c_str());
}
util::ResourcePtr<int, decltype(&::close)> fd(tmp_fd, ::close(fd));

Alternatively, you can use a deleter function that tests the resource value for validity and avoids calling the deleter with an invalid value:

util::ResourcePtr<int, std::function<void(int)>> fd(
::open(filename.c_str(), O_RDONLY),
[](int fd) { if (fd != -1) ::close(fd); }
);

Note that, with the second approach, a call to get() will succeed and return -1 rather than throwing an exception, so the first approach is the recommended one.

template<typename R , typename D >
unity::util::ResourcePtr< R, D >::ResourcePtr ( ResourcePtr< R, D > &&  r)

Constructs a ResourcePtr by transferring ownership from r to this.

If the resource's move or copy constructor throws, the exception is propagated to the caller. The strong exception guarantee is preserved if it is provided by the resource.

template<typename R , typename D >
unity::util::ResourcePtr< R, D >::~ResourcePtr ( )
noexcept

Destroys the ResourcePtr. If a resource is held, it calls the deleter for the current resource (if any).

Member Function Documentation

template<typename R , typename D >
void unity::util::ResourcePtr< R, D >::dealloc ( )

Calls the deleter for the current resource.

If the deleter throws, the resource is considered in the "not allocated" state, that is, no attempt is made to call the deleter again for this resource.

template<typename R , typename D >
R unity::util::ResourcePtr< R, D >::get ( ) const
inline

Returns the current resource. If no resource is currently held, get() throws std::logic_error.

Returns
The current resource (if any).

If the resource's copy constructor throws an exception, that exception is propagated to the caller.

Exceptions
std::logic_errorif has_resource() is false.
template<typename R , typename D >
D & unity::util::ResourcePtr< R, D >::get_deleter ( )
inlinenoexcept
Returns
The deleter for the resource.
template<typename R , typename D >
D const & unity::util::ResourcePtr< R, D >::get_deleter ( ) const
inlinenoexcept
Returns
The deleter for the resource.
template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::has_resource ( ) const
inlinenoexcept
Returns
true if this currently manages a resource; false, otherwise.
template<typename R , typename D >
unity::util::ResourcePtr< R, D >::operator bool ( ) const
inlineexplicitnoexcept

Synonym for has_resource().

template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::operator!= ( ResourcePtr< R, D > const &  rhs) const
inline

Compares two instances for inequality.

If the underlying operator== throws an exception, that exception is propagated to the caller.

Note
This operator is available only if the underlying resource provides operator==.
template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::operator< ( ResourcePtr< R, D > const &  rhs) const

Returns true if this is less than rhs.

An instance that does not hold a resource is less than any instance that holds a resource.

If the underlying operator< throws an exception, that exception is propagated to the caller.

Note
This operator is available only if the underlying resource provides operator<.
template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::operator<= ( ResourcePtr< R, D > const &  rhs) const

Returns true if this is less than or equal to rhs.

An instance that does not hold a resource is less than any instance that holds a resource. Two instances that do not hold a resource are equal.

If the underlying operator< or operator== throws an exception, that exception is propagated to the caller.

Note
This operator is available only if the underlying resource provides operator< and operator==.
template<typename R, typename D>
ResourcePtr& unity::util::ResourcePtr< R, D >::operator= ( ResourcePtr< R, D > const &  )
delete

Deleted

template<typename R , typename D >
ResourcePtr< R, D > & unity::util::ResourcePtr< R, D >::operator= ( ResourcePtr< R, D > &&  r)

Assigns the resource held by r, transferring ownership. After the transfer, r.has_resource() returns false, and this.has_resource() returns the value of r.has_resource() prior to the assignment.

template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::operator== ( ResourcePtr< R, D > const &  rhs) const

Compares two instances for equality.

Two instances that do not hold a resource are equal. An instance that does not hold a resource is not equal to any instance that holds a resource.

If the underlying operator== throws an exception, that exception is propagated to the caller.

Note
This operator is available only if the underlying resource provides operator==.
template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::operator> ( ResourcePtr< R, D > const &  rhs) const
inline

Returns true if this is greater than rhs.

An instance that holds a resource is greater than any instance that does not hold a resource.

If the underlying operator< or operator== throws an exception, that exception is propagated to the caller.

Note
This operator is available only if the underlying resource provides operator< and operator==.
template<typename R , typename D >
bool unity::util::ResourcePtr< R, D >::operator>= ( ResourcePtr< R, D > const &  rhs) const
inline

Returns true if this is greater than or equal to rhs.

An instance that holds a resource is greater than any instance that does not hold a resource. Two instances that do not hold a resource are equal.

If the underlying operator< throws an exception, that exception is propagated to the caller.

Note
This operator is available only if the underlying resource provides operator<.
template<typename R , typename D >
R unity::util::ResourcePtr< R, D >::release ( )
inline

Releases ownership of the current resource without calling the deleter.

Returns
The current resource.
Exceptions
std::logic_errorif has_resource() is false.
template<typename R , typename D >
void unity::util::ResourcePtr< R, D >::reset ( r)

Assigns a new resource to this, first deallocating the current resource (if any).

If the deleter for the current resource throws an exception, the exception is propagated to the caller. In this case, the transfer of r to this is still carried out so, after the call to reset(), this manages r, whether the deleter throws or not. (If the deleter does throw, no attempt is made to call the deleter again for the same resource.)

template<typename R , typename D >
void unity::util::ResourcePtr< R, D >::swap ( ResourcePtr< R, D > &  other)

Swaps the resource and deleter of this with the resource and deleter of other using argument dependent lookup (ADL).

If the underlying swap throws an exception, that exception is propagated to the caller, and the resource held by the ResourcePtr is unchanged.


The documentation for this class was generated from the following file: