-
Notifications
You must be signed in to change notification settings - Fork 241
RAII resource wrapper details
This page documents the details of the WIL resource management classes (resource.h), for those who need to integrate with or debug those classes.
- ownership
The obligation to close or otherwise dispose of another object.
- empty
The state of a resource type when it does not own anything.
The wil::details::resource_policy
traits class decribes how an object
is managed by the wil library's unique_*
classes.
Use this value if you are defining a new resource type and you need
finer control than unique_any_t
provides.
template <typename pointer,
typename close_fn_t,
close_fn_t close_fn,
typename pointer_access = wil::details::pointer_access_all,
typename pointer_storage = pointer,
pointer invalid = pointer(),
typename pointer_invalid = wistd::nullptr_t>
struct resource_policy;
Template parameters
-
pointer
The underlying data type that is managed by theunique_*
wrapper. For types wrapped byunique_ptr
, it is typically a pointer type.
-
close_fn_t
The type of the function that is used to close the underlying resource.- The
close_fn_t
andclose_fn
are usually passed as the pairdecltype(something), something
.
- The
-
close_fn
A unary operation (typically a function) which closes the underlying resource.- It is called with one parameter, a
pointer_storage
containing the resource to be closed. - It will not be called with the
invalid
value.
- It is called with one parameter, a
-
pointer_access
(default ispointer_access_all
)
A pointer access value (see below) which controls visibility of the underlying pointer to clients.
-
pointer_storage
(default ispointer
)
The type used to store the underlying data type. This is usually the same aspointer
, but will be different if the underlying storage is itself a wrapper class, such as a smart pointer. Thepointer_storage
must have an implicit conversion topointer
and vice versa.
-
invalid
(default is null/zero value ofpointer
)
The value which represents that there is no resource. Defaults to the null/zero value of thepointer
type.
-
pointer_invalid
(default iswistd::nullptr_t
)
The typewistd::nullptr_t
if you are allowed toreset
or assignnullptr
to theunique_*
wrapper. If the underlying data type is not a pointer type, then passpointer
instead.
Member types
-
pointer_storage
Thepointer_storage
type specified in the template.
-
pointer
Thepointer
type specified in the template.
-
pointer_access
Thepointer_access
value specified in the template.
-
pointer_invalid
Thepointer_invalid
type specified in the template.
Methods
-
static pointer_storage invalid_value()
Produces theinvalid
value.
-
static bool is_valid(pointer_storage value)
Reports whether the value is theinvalid
value.
-
static void close(pointer_storage value)
Closes the resource represented byvalue
, which will never beinvalid
.
-
static void close_reset(pointer_storage value)
Closes the resource represented byvalue
, which will never beinvalid
, while preserving theGetLastError
value.
The wil::details::pointer_access_*
values control how much access the
client of a unique_*
wrapper has to the wrapped pointer value.
Use this value if you are defining a new resource type and wish to restrict access to the raw pointer.
Value | Can move | Can get()
|
Can release()
|
Can addressof() and &
|
---|---|---|---|---|
wil::details::pointer_access_all |
Yes | Yes | Yes | Yes |
wil::details::pointer_access_noaddress |
Yes | Yes | Yes | No |
wil::details::pointer_access_none |
Yes | No | No | No |
The wil::details::unique_storage
template class is a low-level smart
pointer class which provides the underlying storage and memory
management operations for the unique_*
wrappers. The unique_storage
is an RAII class which manages the lifetime of another object (the
owned object). If the unique_storage
is not managing any object, it
is said to be empty.
A unique_storage
is the size of a pointer_storage
, which is
typically a pointer.
You usually do not need to use this class directly.
It is separate from unique_any_t
to allow a type-specific
specialization class to insert itself into the inheritance chain between
unique_any_t
and unique_storage
. Classes like unique_event
take
advantage of this so that they can be a unique_any
, but with
additional methods like SetEvent
.
template <typename policy>
struct unique_storage;
Template parameters
-
policy
Theresource_policy
that describes the behavior of the resource.
Member types
-
policy
(protected)
Theresource_policy
type specified in the template.
-
pointer_storage
(protected)
Thepointer_storage
type of the policy.
-
pointer
(protected)
Thepointer
type of the policy.
-
base_storage
(protected)
Theunique_storage
class itself.
Constructors
-
unique_storage()
(protected)
Initializes an empty storage. -
unique_storage(pointer_storage ptr)
(protected)
Takes ownership of the provided pointer.
Methods
-
pointer get() const
Returns a pointer to the object being managed, or a policy-defined invalid value (usually a null pointer) if theunique_storage
is empty.
-
void reset(pointer_storage ptr)
Closes the pointer currently being managed and takes ownership of the new pointer.
-
void reset()
Closes the pointer currently being managed and leaves the object empty.
-
void reset(nullptr)
Closes the pointer currently being managed and leaves the object empty. Allowed only if the underlying type is a pointer. (Thepolicy::pointer_invalid
must bewistd::nullptr_t
.)
-
pointer_storage release()
Makes theunique_storage
empty and returns the object that was previously being managed. It is the caller's responsibility to close the returned object. (The pointer access policy must be all or noaddress.)
-
pointer_storage* addressof()
Returns a pointer to the internal pointer storage. (The pointer access policy must be all.)
-
void replace(unique_storage&& other)
(protected)
Closes the pointer currently being managed and takes ownership of the pointer managed by theother
object.
-
bool is_valid() const
(protected)
Returnstrue
if an object is being managed, or orfalse
if theunique_storage
is empty.
Note that the release
method behaves differently from the
same-named method of COM and MFC wrapper classes. The behavior of the
unique_storage
aligns with the C++
standard.
unique_storage |
COM/MFC wrappers | Description |
---|---|---|
reset |
Attach |
Take ownership of a raw pointer. |
release |
Detach |
Return a raw pointer and transfer the ownership to the caller. |
As noted above, you can derive from unique_storage
in order to inject
methods into the underlying type. For example, consider a platform type
HWIDGET
. You could start with a unique_any
declaration:
using unique_widget = unique_any<HWIDGET, decltype(::CloseWidget), ::CloseWidget>;
Operations on widgets would go like this:
unique_widget widget{ CreateWidget() };
WiggleWidget(widget.get());
If you desire to make wiggling a widget more convenient, you could
inject the wiggle
method into the unique_widget
as follows:
class widget_t :
public wil::details::unique_storage<
wil::details::resource_policy<HWIDGET, decltype(::CloseWidget), ::CloseWidget>>
{
public:
// Give the storage type a simpler name.
typedef wil::details::unique_storage<
wil::details::resource_policy<HWIDGET, decltype(::CloseWidget), ::CloseWidget>> storage_t;
// forward all base class constructors
template<typename... args_t>
explicit widget_t(args_t&& ...args) noexcept : storage_t(wistd::forward<args_t>(args)...) {}
// Here is where we can inject additional methods.
void wiggle() const noexcept
{
WiggleWidget(storage_t::get());
}
}
using unique_widget = unique_any_t<widget_t>;
You can now invoke the wiggle
method directly on a unique_widget
:
unique_widget widget{ CreateWidget() };
widget.wiggle();
Use this pattern sparingly. It works best for types (such as kernel events) where clients are not really interested in the handle itself, but rather on the operations availble to the handle.
The wil::unique_any_t
template class is a smart pointer class. It
manages the lifetime of another object (the owned object). If the
unique_any_t
is not managing any object, it is said to be empty.
A unique_any_t
is the size of a pointer_storage
, which is typically
a pointer.
The unique_any_t
type is patterned after the C++ unique_ptr
type. It
is movable but not copyable.
template <typename storage_t>
class unique_any_t : public storage_t;
Template parameters
-
storage_t
A type that ultimately derives fromunique_storage
. In most cases, this is a specialization ofunique_storage
itself. (See Advanced use of unique storage for an example of using some other type.)
Member types
-
policy
Theresource_policy
of theunique_storage
.
-
pointer_storage
Thepointer_storage
type of the policy.
-
pointer
Thepointer
type of the policy.
Constructors
-
unique_any_t(args...)
Constructor parameters are forwarded to thestorage_t
. In the common case where thestorage_t
is aunique_storage
, it takes ownership of the passed-in pointer.
-
unique_any_t()
Creates an emptyunique_any_t
.
-
unique_any_t(nullptr)
Creates an emptyunique_any_t
. (Thepolicy::pointer_invalid
must bewistd::nullptr_t
.)
Operators
-
operator=(unique_any_t&& other) noexcept
Closes the object currently being managed and takes ownership of the object being managed byother
.
-
operator=(nullptr) noexcept
Closes the object currently being managed and leaves theunique_any_t
empty. Allowed only if the underlying type is a pointer. (Thepolicy::pointer_invalid
must bewistd::nullptr_t
.)
-
explicit operator bool() const noexcept
Returnstrue
if an object is being managed, or orfalse
if theunique_any_t
is empty.
-
pointer_storage* operator&() noexcept
Closes the object that is currently being managed and returns a pointer to the internal pointer storage. (The pointer access policy must be all.) To obtain a pointer to the internal pointer storage without closing the current object, use theaddressof
method.
-
==
,!=
,<
,<=
,>
,>=
comparison operators
These perform comparison on the underlyingpointer
. If thepolicy::pointer_invalid
iswistd::nullptr_t
, then equality and inequality comparisons withnullptr
are also supported.
Methods
-
pointer get() const
Returns a pointer to the object being managed, or a policy-defined invalid value (usually a null pointer) if theunique_any_t
is empty. (The pointer access policy must be all or noaddress.)
-
void reset(pointer_storage ptr)
(inherited)
Closes the object currently being managed and takes ownership of the new pointer.
-
void reset()
(inherited)
Closes the object currently being managed and leaves theunique_any_t
empty.
-
void reset(nullptr)
(inherited)
Closes the object currently being managed and leaves theunique_any_t
empty. Allowed only if the underlying type is a pointer. (Thepolicy::pointer_invalid
must bewistd::nullptr_t
.)
-
pointer_storage release()
(inherited)
Makes theunique_any_t
empty and returns the object that was previously being managed. It is the caller's responsibility to close the returned object. (The pointer access policy must be all or noaddress.)
-
pointer_storage* put()
Closes the object that is currently being managed and returns a pointer to the internal pointer storage. (The pointer access policy must be all.) To obtain a pointer to the internal pointer storage without closing the current object, use theaddressof
method.
-
pointer_storage* addressof()
(inherited)
Returns a pointer to the internal pointer storage. (The pointer access policy must be all.)
-
swap(unique_any_t& other) noexcept
Exchanges the owned objects. Also available as a free functionswap(left, right)
for ADL purposes.
The unique_any
alias makes it more convenient to create new unique_*
types.
template <typename pointer,
typename close_fn_t,
close_fn_t close_fn,
typename pointer_access = wil::details::pointer_access_all,
typename pointer_storage = pointer,
pointer invalid = pointer(),
typename pointer_invalid = wistd::nullptr_t>
using unique_any = unique_any_t<details::unique_storage<details::resource_policy<
pointer, close_fn_t, close_fn, pointer_access, pointer_storage, invalid, pointer_invalid>>>;
The template parameters are the same as those for resource_policy
.