-/* -*-c++-*-
- *
- * 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
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program 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 for more details.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
+///@file
+/// Pointer proxy doing reference counting.
+//
+// Copyright (C) 2005-2012 Mathias Froehlich
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 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
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef SGSharedPtr_HXX
#define SGSharedPtr_HXX
#include "SGReferenced.hxx"
+#include <algorithm>
+
+template<typename T>
+class SGWeakPtr;
/// This class is a pointer proxy doing reference counting on the object
/// it is pointing to.
/// The SGSharedPtr class handles reference counting and possible
/// destruction if no nore references are in use automatically.
-/// Classes derived from @SGReferenced can be handled with SGSharedPtr.
+/// Classes derived from SGReferenced can be handled with SGSharedPtr.
/// Once you have a SGSharedPtr available you can use it just like
/// a usual pointer with the exception that you don't need to delete it.
/// Such a reference is initialized by zero if not initialized with a
/// 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)
template<typename U>
SGSharedPtr(const SGSharedPtr<U>& p) : _ptr(p.get())
{ get(_ptr); }
+ template<typename U>
+ explicit SGSharedPtr(const SGWeakPtr<U>& p): _ptr(0)
+ { reset(p.lock().get()); }
~SGSharedPtr(void)
- { put(); }
+ { reset(); }
SGSharedPtr& operator=(const SGSharedPtr& p)
- { assign(p.get()); return *this; }
+ { reset(p.get()); return *this; }
template<typename U>
SGSharedPtr& operator=(const SGSharedPtr<U>& p)
- { assign(p.get()); return *this; }
+ { reset(p.get()); return *this; }
template<typename U>
SGSharedPtr& operator=(U* p)
- { assign(p); return *this; }
+ { reset(p); return *this; }
T* operator->(void) const
{ return _ptr; }
{ return _ptr; }
T* release()
{ T* tmp = _ptr; _ptr = 0; T::put(tmp); return tmp; }
+ void reset()
+ { if (!T::put(_ptr)) delete _ptr; _ptr = 0; }
+ void reset(T* p)
+ { SGSharedPtr(p).swap(*this); }
bool isShared(void) const
{ return T::shared(_ptr); }
{ return _ptr != (T*)0; }
void clear()
- { put(); }
- void swap(SGSharedPtr& sharedPtr)
- { T* tmp = _ptr; _ptr = sharedPtr._ptr; sharedPtr._ptr = tmp; }
+ { reset(); }
+ void swap(SGSharedPtr& other)
+ { std::swap(_ptr, other._ptr); }
private:
- void assign(T* p)
- { get(p); put(); _ptr = p; }
void assignNonRef(T* p)
- { put(); _ptr = p; }
+ { reset(); _ptr = p; }
void get(const T* p) const
{ T::get(p); }
- void put(void)
- { if (!T::put(_ptr)) delete _ptr; _ptr = 0; }
// The reference itself.
T* _ptr;
{
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