//################################################################################################## // // Custom Visualization Core library // Copyright (C) 2011-2013 Ceetron AS // // This library may be used under the terms of either the GNU General Public License or // the GNU Lesser General Public License as follows: // // GNU General Public License Usage // This library is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at <> // for more details. // // GNU Lesser General Public License Usage // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU Lesser General Public License at <> // for more details. // //################################################################################################## namespace external { namespace cvf { //-------------------------------------------------------------------------------------------------- /// Constructor. Set the ref count to zero //-------------------------------------------------------------------------------------------------- inline Object::Object() : m_refCount(0) { #if ((CVF_TRACK_ACTIVE_OBJECT_INSTANCES >= 1 && defined(_DEBUG)) || CVF_TRACK_ACTIVE_OBJECT_INSTANCES == 2) activeObjectInstances()->insert(this); #endif } //-------------------------------------------------------------------------------------------------- /// Destructor. Asserts that the ref count is zero. //-------------------------------------------------------------------------------------------------- inline Object::~Object() { CVF_ASSERT(m_refCount == 0); #if ((CVF_TRACK_ACTIVE_OBJECT_INSTANCES >= 1 && defined(_DEBUG)) || CVF_TRACK_ACTIVE_OBJECT_INSTANCES == 2) activeObjectInstances()->erase(this); #endif } //-------------------------------------------------------------------------------------------------- /// Increments reference count. /// /// \return The new reference count. //-------------------------------------------------------------------------------------------------- inline int Object::addRef() const { CVF_TIGHT_ASSERT(this); return ++m_refCount; } //-------------------------------------------------------------------------------------------------- /// Decrements the reference count. Returns the new reference count. /// /// \return The new reference count. /// /// If the new reference count is zero, the object (this) is deleted.\n //-------------------------------------------------------------------------------------------------- inline int Object::release() const { CVF_TIGHT_ASSERT(m_refCount > 0); if (--m_refCount == 0) { delete this; return 0; } else { return m_refCount; } } //-------------------------------------------------------------------------------------------------- /// Returns the current reference count //-------------------------------------------------------------------------------------------------- inline int Object::refCount() const { CVF_TIGHT_ASSERT(this); return m_refCount; } //================================================================================================== /// /// \class cvf::ref /// \ingroup Core /// /// Smart pointer class used for handling reference counted objects (that derive from Object). /// /// The ref class encapsulates reference counting by calling Object::addRef() and Object::release() /// on the internally stored object pointer. /// /// \internal Inspired by boost's intrusive_ptr class. //================================================================================================== //-------------------------------------------------------------------------------------------------- /// Constructor from naked pointer /// /// Will call addRef() on the passed object. //-------------------------------------------------------------------------------------------------- template ref::ref(T* object) { if (object) { object->addRef(); m_object = object; } else { m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// Copy constructor /// /// Copies the internal pointer from the passed ref object and calls addRef() on the object. //-------------------------------------------------------------------------------------------------- template ref::ref(const ref& other) { if (other.m_object) { other.m_object->addRef(); m_object = other.m_object; } else { m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// Construct from related. /// /// Copies the internal pointer from the passed ref object and calls addRef() on the object. //-------------------------------------------------------------------------------------------------- template template ref::ref(const ref& other) { if (other.notNull()) { other->addRef(); // Escape const m_object = const_cast(other.p()); } else { m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// Destructor. /// /// Will call release() on the internal pointer. //-------------------------------------------------------------------------------------------------- template ref::~ref() { if (m_object) { m_object->release(); m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// Assignment from raw pointer. //-------------------------------------------------------------------------------------------------- template ref& ref::operator=(T* rhs) { // Copy-and-swap (on temporary obj) ref(rhs).swap(*this); return *this; } //-------------------------------------------------------------------------------------------------- /// Assignment operator /// /// Copies the internal pointer from \a rhs and calls addRef(). /// If we're already storing an internal pointer, this pointer will be release()'ed. //-------------------------------------------------------------------------------------------------- template ref& ref::operator=(ref rhs) { // Copy-and-swap (copy already done since parameter is passed by value) rhs.swap(*this); return *this; } //-------------------------------------------------------------------------------------------------- /// Assignment from related. /// /// Copies the internal pointer from \a rhs and calls addRef(). /// If we're already storing an internal pointer, this pointer will be release()'ed. //-------------------------------------------------------------------------------------------------- template template ref& ref::operator=(const ref& rhs) { // Copy-and-swap (on temporary obj) ref(rhs).swap(*this); return *this; } //-------------------------------------------------------------------------------------------------- /// Returns the naked pointer this object is associated with. /// /// Added to be able to write the same code for smart pointers as for normal naked pointers. /// /// \code /// ref myObject = new MyObject; /// myObject->doSomething(); // Easier than myObject.p()->doSomething() /// \endcode //-------------------------------------------------------------------------------------------------- template inline T* ref::operator->() { CVF_TIGHT_ASSERT(m_object); return m_object; } //-------------------------------------------------------------------------------------------------- /// Returns naked const pointer this object is associated with. //-------------------------------------------------------------------------------------------------- template inline const T* ref::operator->() const { CVF_TIGHT_ASSERT(m_object); return m_object; } //-------------------------------------------------------------------------------------------------- /// Dereference operator returning a modifiable reference to the associated object. /// /// Added to be able to write the same code for smart pointers as for normal naked pointers. /// \code /// ref myObject = new MyObject; /// *myObject.doSomething(); /// \endcode //-------------------------------------------------------------------------------------------------- template inline T& ref::operator*() { CVF_TIGHT_ASSERT(m_object); return *m_object; } //-------------------------------------------------------------------------------------------------- /// Dereference operator returning a const reference to the associated object. //-------------------------------------------------------------------------------------------------- template inline const T& ref::operator*() const { CVF_TIGHT_ASSERT(m_object); return *m_object; } //-------------------------------------------------------------------------------------------------- /// Returns the naked pointer //-------------------------------------------------------------------------------------------------- template inline T* ref::p() { return m_object; } //-------------------------------------------------------------------------------------------------- /// Returns naked const pointer //-------------------------------------------------------------------------------------------------- template inline const T* ref::p() const { return m_object; } //-------------------------------------------------------------------------------------------------- /// Returns true if the internal pointer is NULL //-------------------------------------------------------------------------------------------------- template inline bool ref::isNull() const { return m_object == NULL; } //-------------------------------------------------------------------------------------------------- /// Returns true if the internal pointer is different from NULL //-------------------------------------------------------------------------------------------------- template inline bool ref::notNull() const { return m_object != NULL; } //-------------------------------------------------------------------------------------------------- /// Does less than comparison of two ref objects. /// /// \return Returns true if this object's internal pointer is less than the internal pointer of \a rhs. /// /// The comparison is done by comparing the internal pointer values ( this.p() < rhs.p() ) /// This operator is used in several STL collections (e.g. std::set) as well as in many STL algorithms /// (e.g. std::sort() ). //-------------------------------------------------------------------------------------------------- template bool ref::operator<(const ref& rhs) const { CVF_TIGHT_ASSERT((m_object != NULL) && (rhs.p() != NULL)); return std::less()(m_object, rhs.m_object); } //-------------------------------------------------------------------------------------------------- /// Exchanges the contents of the two smart pointers. /// /// \param other Modifiable reference to the ref object that should have its contents swapped. /// /// Swap the associated pointer in this and the passed ref object. Will not modify the reference /// count of any of the associated objects. /// /// \warning Note that signature differs from normal practice. This is done to be /// consistent with the signature of std::swap() //-------------------------------------------------------------------------------------------------- template void ref::swap(ref& other) { T* tmp = other.m_object; other.m_object = m_object; m_object = tmp; } //================================================================================================== /// /// \class cvf::cref /// \ingroup Core /// /// Smart pointer class used for handling const reference counted objects //================================================================================================== //-------------------------------------------------------------------------------------------------- /// Construct from naked pointer //-------------------------------------------------------------------------------------------------- template cref::cref(const T* object) { if (object) { object->addRef(); m_object = object; } else { m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// Copy constructor //-------------------------------------------------------------------------------------------------- template cref::cref(const cref& other) { if (other.m_object) { other.m_object->addRef(); m_object = other.m_object; } else { m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// Construct from related //-------------------------------------------------------------------------------------------------- template template cref::cref(const cref& other) { if (other.notNull()) { other->addRef(); m_object = other.p(); } else { m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template cref::~cref() { if (m_object) { m_object->release(); m_object = NULL; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template cref& cref::operator=(const T* rhs) { // Copy-and-swap (on temporary obj) cref(rhs).swap(*this); return *this; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template cref& cref::operator=(cref rhs) { // Copy-and-swap (copy already done since parameter is passed by value) rhs.swap(*this); return *this; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template template cref& cref::operator=(const cref& rhs) { // Copy-and-swap (on temporary obj) cref(rhs).swap(*this); return *this; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template inline const T* cref::operator->() const { CVF_TIGHT_ASSERT(m_object); return m_object; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template inline const T& cref::operator*() const { CVF_TIGHT_ASSERT(m_object); return *m_object; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template inline const T* cref::p() const { return m_object; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template inline bool cref::isNull() const { return m_object == NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template inline bool cref::notNull() const { return m_object != NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template bool cref::operator<(const cref& rhs) const { CVF_TIGHT_ASSERT((m_object != NULL) && (rhs.p() != NULL)); return std::less()(m_object, rhs.m_object); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- template void cref::swap(cref& other) { const T* tmp = other.m_object; other.m_object = m_object; m_object = tmp; } //-------------------------------------------------------------------------------------------------- /// Creation of smart pointers. //-------------------------------------------------------------------------------------------------- template ref make_ref(Args&&... args) { return cvf::ref(new T(args...)); } //-------------------------------------------------------------------------------------------------- /// Creation of const smart pointers. //-------------------------------------------------------------------------------------------------- template cref make_cref(Args&&... args) { return cvf::cref(new T(args...)); } } // namespace cvf } //namespace external