📄 scoped_handle.hpp
字号:
STLSOFT_MESSAGE_ASSERT("function pointer must not be NULL", NULL != fn);
fn();
}
};
# endif /* STLSOFT_CF_STDCALL_SUPPORTED */
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/** \brief Provides automated scope-based cleanup of arbitrary resource
* types without any memory allocation required to implement the generic
* support.
*
* \ingroup group__library__smart_pointers
*
* The template is parameterised on the resource type (e.g. FILE*, int, void*)
* and instances are initialised from a resource handle and the address of a
* (single-parameter) cleanup function, as in:
*
\code
::stlsoft::scoped_handle<void*> h3(::malloc(100), ::free);
\endcode
*
* or:
*
\code
::stlsoft::scoped_handle<int> h1(::open("file.ext"), ::close);
\endcode
*
* or:
*
\code
FILE *file = ::fopen("file.ext", "r");
::stlsoft::scoped_handle<FILE*> h2(file, ::fclose);
\endcode
*
* \note This class provides externally-initialised immutable-RAII (see section
* 3.5 of Imperfect C++; http://imperfectcplusplus.com/). The managed resource
* must be provided in the constructor, and the managing instance cannot be set
* to manage another resource. However, there is a nod to convenience in so far
* as there is a detach() method, which can be used to clear the resource from
* the managing instance and return it to the calling context.
*/
template<ss_typename_param_k H>
class scoped_handle
{
/// \name Types
/// @{
private:
typedef void (STLSOFT_CDECL *degenerate_function_type)();
typedef H_holder<H> holder_type;
public:
/// \brief The resource type
typedef H resource_type;
/// \brief The handle type
typedef H handle_type;
/// \brief The instantiation of the type
typedef scoped_handle<H> class_type;
/// @}
/// \name Construction
/// @{
public:
#ifdef STLSOFT_CF_CDECL_SUPPORTED
# if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED)
/// \brief Construct from a resource handle and a clean-up function with void return type
scoped_handle( resource_type h
, void (STLSOFT_CDECL *f)(resource_type)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_cdecl<H, void>::translate)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
/// \brief Construct from a resource handle and an indirect clean-up function with void return type
scoped_handle( resource_type *ph
, void (STLSOFT_CDECL *f)(resource_type*)
, resource_type hNull = 0)
: m_hh(ph)
, m_hNull(hNull)
, m_tfn(&function_translator_cdecl<H, void>::translate_indirect)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
# endif /* !STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT || STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED */
# if defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT)
/// \brief Construct from a resource handle and a clean-up function with non-void return type
template <ss_typename_param_k R>
scoped_handle( resource_type h
, R (STLSOFT_CDECL *f)(resource_type)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_cdecl<H, R>::translate)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
/// \brief Construct from a resource handle and an indirect clean-up function with non-void return type
template <ss_typename_param_k R>
scoped_handle( resource_type *ph
, R (STLSOFT_CDECL *f)(resource_type*)
, resource_type hNull = 0)
: m_hh(ph)
, m_hNull(hNull)
, m_tfn(&function_translator_cdecl<H, R>::translate_indirect)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
# endif /* STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT */
#endif /* STLSOFT_CF_CDECL_SUPPORTED */
#ifdef STLSOFT_CF_FASTCALL_SUPPORTED
# if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED)
/// \brief Construct from a resource handle and a clean-up "fastcall" function with void return type
scoped_handle( resource_type h
, void (STLSOFT_FASTCALL *f)(resource_type)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_fastcall<H, void>::translate)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
/// \brief Construct from a resource handle and an indirect clean-up "fastcall" function with void return type
scoped_handle( resource_type h
, void (STLSOFT_FASTCALL *f)(resource_type *)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_fastcall<H, void>::translate_indirect)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
# endif /* !STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT || STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED */
# if defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT)
/// \brief Construct from a resource handle and a clean-up "fastcall" function with non-void return type
template <ss_typename_param_k R>
scoped_handle( resource_type h
, R (STLSOFT_FASTCALL *f)(resource_type)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_fastcall<H, R>::translate)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
/// \brief Construct from a resource handle and an indirect clean-up "fastcall" function with non-void return type
template <ss_typename_param_k R>
scoped_handle( resource_type *ph
, R (STLSOFT_FASTCALL *f)(resource_type*)
, resource_type hNull = 0)
: m_hh(ph)
, m_hNull(hNull)
, m_tfn(&function_translator_fastcall<H, R>::translate_indirect)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
# endif /* STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT */
#endif /* STLSOFT_CF_FASTCALL_SUPPORTED */
#ifdef STLSOFT_CF_STDCALL_SUPPORTED
# if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED)
/// \brief Construct from a resource handle and a clean-up "stdcall" function with void return type
scoped_handle( resource_type h
, void (STLSOFT_STDCALL *f)(resource_type)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_stdcall<H, void>::translate)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
/// \brief Construct from a resource handle and an indirect clean-up "stdcall" function with void return type
scoped_handle( resource_type *ph
, void (STLSOFT_STDCALL *f)(resource_type*)
, resource_type hNull = 0)
: m_hh(ph)
, m_hNull(hNull)
, m_tfn(&function_translator_stdcall<H, void>::translate_indirect)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
# endif /* !STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT || STLSOFT_CF_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED */
# if defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT)
/// \brief Construct from a resource handle and a clean-up "stdcall" function with non-void return type
template <ss_typename_param_k R>
scoped_handle( resource_type h
, R (STLSOFT_STDCALL *f)(resource_type)
, resource_type hNull = 0)
: m_hh(h)
, m_hNull(hNull)
, m_tfn(&function_translator_stdcall<H, R>::translate)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
/// \brief Construct from a resource handle and an indirect clean-up "stdcall" function with non-void return type
template <ss_typename_param_k R>
scoped_handle( resource_type *ph
, R (STLSOFT_STDCALL *f)(resource_type*)
, resource_type hNull = 0)
: m_hh(ph)
, m_hNull(hNull)
, m_tfn(&function_translator_stdcall<H, R>::translate_indirect)
, m_fn(reinterpret_cast<degenerate_function_type>(f))
{
STLSOFT_MESSAGE_ASSERT("Precondition violation: cannot initialise with a NULL function pointer", NULL != f);
}
# endif /* STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT */
#endif /* STLSOFT_CF_STDCALL_SUPPORTED */
/// \brief "Releases" the managed resource.
///
/// Invokes the cleanup function, unless close() or detach() have
/// already been called
~scoped_handle()
{
STLSOFT_MESSAGE_ASSERT("Invariant violation: function pointer must not be NULL", NULL != m_fn);
if(!empty())
{
m_tfn(m_hh, m_fn);
}
}
/// @}
/// \name Attributes
/// @{
public:
/// \brief Indicates whether the instance holds a non-"null" resource
bool empty() const
{
STLSOFT_MESSAGE_ASSERT("Invariant violation: function pointer must not be NULL", NULL != m_fn);
return get_null_value_() == m_hh.get();
}
/// @}
/// \name Operations
/// @{
public:
/// \brief Closes the handle immediately
///
/// \note Calling this method more than once has no effect.
void close()
{
STLSOFT_MESSAGE_ASSERT("Invariant violation: function pointer must not be NULL", NULL != m_fn);
if(!empty())
{
m_tfn(m_hh, m_fn);
m_hh.set(get_null_value_());
}
}
/// \brief Detaches the resource, and returns it to the caller.
///
/// \remarks Calling this method removes the resource from the managing
/// instance, so it will not be automatically closed.
resource_type detach()
{
STLSOFT_MESSAGE_ASSERT("Invariant violation: function pointer must not be NULL", NULL != m_fn);
resource_type h = m_hh.get();
m_hh.set(get_null_value_());
return h;
}
/// @}
/// \name Accessors
/// @{
public:
/// \brief Provides the bare resource handle to the caller. Does not
/// detach the handle from the managing instance.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -