/* -*-c++-*-
*
- * Copyright (C) 2005-2006 Mathias Froehlich
+ * Copyright (C) 2005-2012 Mathias Froehlich
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/// to zero and consequently the objects will never be destroyed.
/// Always try to use directed graphs where the references away from the
/// top node are made with SGSharedPtr's and the back references are done with
-/// ordinary pointers.
+/// ordinary pointers or SGWeakPtr's.
/// There is a very good description of OpenSceneGraphs ref_ptr which is
/// pretty much the same than this one at
/// http://dburns.dhs.org/OSG/Articles/RefPointers/RefPointers.html
+template<typename T>
+class SGWeakPtr;
+
template<typename T>
class SGSharedPtr {
public:
+ typedef T element_type;
+
SGSharedPtr(void) : _ptr(0)
{}
SGSharedPtr(T* ptr) : _ptr(ptr)
{ get(_ptr); }
- SGSharedPtr(const SGSharedPtr& p) : _ptr(p.ptr())
+ SGSharedPtr(const SGSharedPtr& p) : _ptr(p.get())
{ get(_ptr); }
template<typename U>
- SGSharedPtr(const SGSharedPtr<U>& p) : _ptr(p.ptr())
+ SGSharedPtr(const SGSharedPtr<U>& p) : _ptr(p.get())
{ get(_ptr); }
~SGSharedPtr(void)
{ put(); }
SGSharedPtr& operator=(const SGSharedPtr& p)
- { assign(p.ptr()); return *this; }
+ { assign(p.get()); return *this; }
template<typename U>
SGSharedPtr& operator=(const SGSharedPtr<U>& p)
- { assign(p.ptr()); return *this; }
+ { assign(p.get()); return *this; }
template<typename U>
SGSharedPtr& operator=(U* p)
{ assign(p); return *this; }
{ return _ptr; }
T* ptr(void) const
{ return _ptr; }
+ T* get(void) const
+ { return _ptr; }
+ T* release()
+ { T* tmp = _ptr; _ptr = 0; T::put(tmp); return tmp; }
bool isShared(void) const
- { return SGReferenced::shared(_ptr); }
+ { return T::shared(_ptr); }
unsigned getNumRefs(void) const
- { return SGReferenced::count(_ptr); }
+ { return T::count(_ptr); }
bool valid(void) const
- { return _ptr; }
+ { return _ptr != (T*)0; }
+
+ void clear()
+ { put(); }
+ void swap(SGSharedPtr& sharedPtr)
+ { T* tmp = _ptr; _ptr = sharedPtr._ptr; sharedPtr._ptr = tmp; }
private:
void assign(T* p)
{ get(p); put(); _ptr = p; }
+ void assignNonRef(T* p)
+ { put(); _ptr = p; }
void get(const T* p) const
- { SGReferenced::get(p); }
+ { T::get(p); }
void put(void)
- { if (!SGReferenced::put(_ptr)) { delete _ptr; _ptr = 0; } }
+ { if (!T::put(_ptr)) delete _ptr; _ptr = 0; }
// The reference itself.
T* _ptr;
+
+ template<typename U>
+ friend class SGWeakPtr;
};
+/**
+ * Support for boost::mem_fn
+ */
+template<typename T>
+T* get_pointer(SGSharedPtr<T> const & p)
+{
+ return p.ptr();
+}
+
+/**
+ * static_cast for SGSharedPtr
+ */
+template<class T, class U>
+SGSharedPtr<T> static_pointer_cast(SGSharedPtr<U> const & r)
+{
+ return SGSharedPtr<T>( static_cast<T*>(r.get()) );
+}
+
+/**
+ * Compare two SGSharedPtr<T> objects for equality.
+ *
+ * @note Only pointer values are compared, not the actual objects they are
+ * pointing at.
+ */
+template<class T, class U>
+bool operator==(const SGSharedPtr<T>& lhs, const SGSharedPtr<U>& rhs)
+{
+ return lhs.get() == rhs.get();
+}
+
+/**
+ * Compare two SGSharedPtr<T> objects for equality.
+ *
+ * @note Only pointer values are compared, not the actual objects they are
+ * pointing at.
+ */
+template<class T, class U>
+bool operator!=(const SGSharedPtr<T>& lhs, const SGSharedPtr<U>& rhs)
+{
+ return lhs.get() != rhs.get();
+}
+
+/**
+ * Compare two SGSharedPtr<T> objects for weak ordering.
+ *
+ * @note Only pointer values are compared, not the actual objects they are
+ * pointing at.
+ * @note This allows using SGSharedPtr as key in associative containers like for
+ * example std::map and std::set.
+ */
+template<class T, class U>
+bool operator<(const SGSharedPtr<T>& lhs, const SGSharedPtr<U>& rhs)
+{
+ return lhs.get() < rhs.get();
+}
#endif