123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
- *
- * This library is open source and may be redistributed and/or modified under
- * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
- * (at your option) any later version. The full license is in LICENSE file
- * included with this distribution, and on the openscenegraph.org website.
- *
- * 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
- * OpenSceneGraph Public License for more details.
- */
- #ifndef OSG_REF_PTR
- #define OSG_REF_PTR 1
- #include <osg/Config>
- #ifdef OSG_USE_REF_PTR_SAFE_DEREFERENCE
- #include <typeinfo>
- #include <stdexcept>
- #include <string>
- #endif
- namespace osg {
- template<typename T> class observer_ptr;
- /** Smart pointer for handling referenced counted objects.*/
- template<class T>
- class ref_ptr
- {
- public:
- typedef T element_type;
- ref_ptr() : _ptr(0) {}
- ref_ptr(T* ptr) : _ptr(ptr) { if (_ptr) _ptr->ref(); }
- ref_ptr(const ref_ptr& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); }
- template<class Other> ref_ptr(const ref_ptr<Other>& rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); }
- ref_ptr(observer_ptr<T>& optr) : _ptr(0) { optr.lock(*this); }
- ~ref_ptr() { if (_ptr) _ptr->unref(); _ptr = 0; }
- ref_ptr& operator = (const ref_ptr& rp)
- {
- assign(rp);
- return *this;
- }
- template<class Other> ref_ptr& operator = (const ref_ptr<Other>& rp)
- {
- assign(rp);
- return *this;
- }
- inline ref_ptr& operator = (T* ptr)
- {
- if (_ptr==ptr) return *this;
- T* tmp_ptr = _ptr;
- _ptr = ptr;
- if (_ptr) _ptr->ref();
- // unref second to prevent any deletion of any object which might
- // be referenced by the other object. i.e rp is child of the
- // original _ptr.
- if (tmp_ptr) tmp_ptr->unref();
- return *this;
- }
- #ifdef OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION
- // implicit output conversion
- operator T*() const { return _ptr; }
- #else
- // comparison operators for ref_ptr.
- bool operator == (const ref_ptr& rp) const { return (_ptr==rp._ptr); }
- bool operator == (const T* ptr) const { return (_ptr==ptr); }
- friend bool operator == (const T* ptr, const ref_ptr& rp) { return (ptr==rp._ptr); }
- bool operator != (const ref_ptr& rp) const { return (_ptr!=rp._ptr); }
- bool operator != (const T* ptr) const { return (_ptr!=ptr); }
- friend bool operator != (const T* ptr, const ref_ptr& rp) { return (ptr!=rp._ptr); }
- bool operator < (const ref_ptr& rp) const { return (_ptr<rp._ptr); }
- // follows is an implementation of the "safe bool idiom", details can be found at:
- // http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool
- // http://lists.boost.org/Archives/boost/2003/09/52856.php
- private:
- typedef T* ref_ptr::*unspecified_bool_type;
- public:
- // safe bool conversion
- operator unspecified_bool_type() const { return valid()? &ref_ptr::_ptr : 0; }
- #endif
- T& operator*() const
- {
- #ifdef OSG_USE_REF_PTR_SAFE_DEREFERENCE
- if( !_ptr ) {
- // pointer is invalid, so throw an exception
- throw std::runtime_error(std::string("could not dereference invalid osg pointer ") + std::string(typeid(T).name()));
- }
- #endif
- return *_ptr;
- }
- T* operator->() const
- {
- #ifdef OSG_USE_REF_PTR_SAFE_DEREFERENCE
- if( !_ptr ) {
- // pointer is invalid, so throw an exception.
- throw std::runtime_error(std::string("could not call invalid osg pointer ") + std::string(typeid(T).name()));
- }
- #endif
- return _ptr;
- }
- T* get() const { return _ptr; }
- bool operator!() const { return _ptr==0; } // not required
- bool valid() const { return _ptr!=0; }
- /** release the pointer from ownership by this ref_ptr<>, decrementing the objects refencedCount() via unref_nodelete() to prevent the Object
- * object from being deleted even if the reference count goes to zero. Use when using a local ref_ptr<> to an Object that you want to return
- * from a function/method via a C pointer, whilst preventing the normal ref_ptr<> destructor from cleaning up the object. When using release()
- * you are implicitly expecting other code to take over management of the object, otherwise a memory leak will result. */
- T* release() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp; }
- void swap(ref_ptr& rp) { T* tmp=_ptr; _ptr=rp._ptr; rp._ptr=tmp; }
- private:
- template<class Other> void assign(const ref_ptr<Other>& rp)
- {
- if (_ptr==rp._ptr) return;
- T* tmp_ptr = _ptr;
- _ptr = rp._ptr;
- if (_ptr) _ptr->ref();
- // unref second to prevent any deletion of any object which might
- // be referenced by the other object. i.e rp is child of the
- // original _ptr.
- if (tmp_ptr) tmp_ptr->unref();
- }
- template<class Other> friend class ref_ptr;
- T* _ptr;
- };
- template<class T> inline
- void swap(ref_ptr<T>& rp1, ref_ptr<T>& rp2) { rp1.swap(rp2); }
- template<class T> inline
- T* get_pointer(const ref_ptr<T>& rp) { return rp.get(); }
- template<class T, class Y> inline
- ref_ptr<T> static_pointer_cast(const ref_ptr<Y>& rp) { return static_cast<T*>(rp.get()); }
- template<class T, class Y> inline
- ref_ptr<T> dynamic_pointer_cast(const ref_ptr<Y>& rp) { return dynamic_cast<T*>(rp.get()); }
- template<class T, class Y> inline
- ref_ptr<T> const_pointer_cast(const ref_ptr<Y>& rp) { return const_cast<T*>(rp.get()); }
- }
- #endif
|