]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGSharedPtr.hxx
Fix PagedLOD for random objects.
[simgear.git] / simgear / structure / SGSharedPtr.hxx
index c815a2fa566f94253282109ec6d5a76ce4489dad..3afcfc9103bf69d6eff446c039899d74f07c1362 100644 (file)
@@ -1,33 +1,36 @@
-/* -*-c++-*-
- *
- * Copyright (C) 2005-2009 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)
@@ -57,17 +59,20 @@ public:
   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; }
@@ -81,6 +86,10 @@ public:
   { 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); }
@@ -91,20 +100,16 @@ public:
   { 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;
@@ -121,4 +126,51 @@ 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