Skip to content

Instantly share code, notes, and snippets.

@parsd
Created May 12, 2017 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parsd/7a06af2fa6b5df9f3de4199369eb2347 to your computer and use it in GitHub Desktop.
Save parsd/7a06af2fa6b5df9f3de4199369eb2347 to your computer and use it in GitHub Desktop.
Smart handle implementation to automatically manage ownership of Common Vision Blox reference counted object handles.
// ---------------------------------------------------------------------------
/// \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);
}
}
@parsd
Copy link
Author

parsd commented May 12, 2017

Here is an example on how to use this:

CVB::CvbHandle OpenDriverPort(const char *driver, int portNumber)
{
  IMG hImg = nullptr;
  
  if(LoadImageFile(driver, hImg))
  {
    cvbdim_t currentPort = -1;
    if(CS2GetCamPort(hImg, currentPort) >= 0 && currentPort != portNumber)
    {
      IMG hNewPort = nullptr;
      if(CS2SetCamPort(hImg, portNumber, 0, hNewPort) >= 0)
      {
        ReleaseObject(hImg);
        hImg = hNewPort;
      }
    }
  }

  return CVB::CvbHandle(hImg, CVB::Share::No);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment