Smart handle implementation to automatically manage ownership of Common Vision Blox reference counted object handles.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// --------------------------------------------------------------------------- | |
/// \file CvbHandle.h | |
/// | |
/// Declaration and implementation of CVB::CvbHandle. | |
/// | |
/// This implementation requires C++ 11. | |
// --------------------------------------------------------------------------- | |
#pragma once | |
#include <utility> | |
#include <iCVCImg.h> | |
namespace CVB | |
{ | |
/// Defines user choice whether the reference count is to be shared or not. | |
enum class Share | |
{ | |
Yes, ///< Do increment the reference count. | |
No ///< Do not share the reference count. | |
}; | |
// ------------------------------------------------------------------------- | |
/// \brief Manages ownership of CVB reference counted objects. | |
/// | |
/// If you define \c CVB_EXPLICIT_HANDLE before including this header, no | |
/// implicit conversion to the underlying handle is possible. | |
// ------------------------------------------------------------------------- | |
class CvbHandle final | |
{ | |
OBJ handle_; ///< \internal Object handle. | |
public: | |
// ----------------------------------------------------------------------- | |
/// \brief Default ctor. | |
/// | |
/// \post Empty (invalid) handle. | |
// ----------------------------------------------------------------------- | |
CvbHandle() noexcept : handle_(nullptr) {} | |
// ----------------------------------------------------------------------- | |
/// \brief Create management object from the given \a handle. | |
/// | |
/// If you want to adopt the ownership of a handle use Share::No for | |
/// \a doShare. This is e.g. for returned handles from C functions. If you | |
/// want to share ownership (e.g. if you get the handle from an ActiveX | |
/// control) you use Share::Yes for \a doShare. | |
/// | |
/// \param [in] handle Object handle to manage. | |
/// \param [in] doShare Share ownership if Share::Yes. | |
/// | |
/// \post If \a handle is not \b nullptr a valid, owned handle; otherwise | |
/// empty (invalid) handle. | |
// ----------------------------------------------------------------------- | |
CvbHandle(OBJ handle, Share doShare) noexcept | |
: handle_(handle) | |
{ | |
if(doShare == Share::Yes) | |
ShareObject(handle); | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Copy ctor. | |
/// | |
/// This shares the handle's object reference count. | |
/// | |
/// \param [in] rhs Object to copy handle from. | |
/// | |
/// \post Same state as \a rhs. Incremented reference count. | |
// ----------------------------------------------------------------------- | |
CvbHandle(CvbHandle &rhs) noexcept | |
: handle_(rhs.handle_) | |
{ | |
ShareObject(handle_); | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Assignment operator. | |
/// | |
/// This shares the handle's object reference count. | |
/// | |
/// \param [in] rhs Object to copy handle from. | |
/// | |
/// \post Same state as \a rhs. Incremented reference count of \a rhs | |
/// object's handle. This object's old handle is released | |
/// (decremented by one). | |
// ----------------------------------------------------------------------- | |
CvbHandle &operator =(CvbHandle &rhs) noexcept | |
{ | |
if(this != &rhs) | |
CvbHandle(rhs).Swap(*this); | |
return *this; | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Move ctor. | |
/// | |
/// This moves the handle from \a rhs without affecting the reference | |
/// count. Ownership gets transferred to this object. | |
/// | |
/// \param [in] rhs Object to move handle from. | |
/// | |
/// \post Same state as \a rhs. Invalid state in \a rhs. | |
// ----------------------------------------------------------------------- | |
CvbHandle(CvbHandle &&rhs) noexcept | |
: handle_(rhs.handle_) | |
{ | |
rhs.handle_ = nullptr; | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Move assignment operator. | |
/// | |
/// This moves the handle from \a rhs without affecting the reference | |
/// count. Ownership gets transferred to this object. | |
/// | |
/// \param [in] rhs Object to move handle from. | |
/// | |
/// \post Same state as \a rhs. Invalid state in \a rhs. This object's old | |
/// handle is released (decremented by one). | |
// ----------------------------------------------------------------------- | |
CvbHandle & operator =(CvbHandle &&rhs) noexcept | |
{ | |
if(this != &rhs) | |
CvbHandle(std::move(rhs)).Swap(*this); | |
return *this; | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Dtor. | |
/// | |
/// This releases ownership of the handle's object (decrements the | |
/// reference count). | |
// ----------------------------------------------------------------------- | |
~CvbHandle() noexcept | |
{ | |
ReleaseObject(handle_); | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Explicitly checks whether this handle is valid. | |
/// | |
/// \returns \b true if this object's handle is not \b nullptr; \b false | |
/// otherwise. | |
// ----------------------------------------------------------------------- | |
explicit operator bool() const noexcept | |
{ | |
return handle_ != nullptr; | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Explicit conversion to the underlying handle. | |
/// | |
/// \return The underlying handle. | |
/// | |
/// \post State not changed. | |
// ----------------------------------------------------------------------- | |
#ifdef CVB_EXPLICIT_HANDLE | |
explicit | |
#endif | |
operator OBJ() const noexcept | |
{ | |
return handle_; | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Gets access to the underlying handle. | |
/// | |
/// \return The underlying handle. | |
/// | |
/// \post State not changed. | |
// ----------------------------------------------------------------------- | |
OBJ Get() const noexcept | |
{ | |
return handle_; | |
} | |
// ----------------------------------------------------------------------- | |
/// \brief Swaps the handles of \b this object with the given one. | |
/// | |
/// \param [in] rhs Object to swap handles with. | |
/// | |
/// \post Handles of both objects are swapped. | |
// ----------------------------------------------------------------------- | |
void Swap(CvbHandle &rhs) noexcept | |
{ | |
std::swap(handle_, rhs.handle_); | |
} | |
}; | |
} | |
namespace std | |
{ | |
// specialization of std::swap for CVB::CvbHandle | |
template <> | |
inline void swap(CVB::CvbHandle &lhs, CVB::CvbHandle &rhs) noexcept | |
{ | |
lhs.Swap(rhs); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is an example on how to use this: