]> git.mxchange.org Git - simgear.git/commitdiff
Mathias Fröhlich:
authorehofman <ehofman>
Thu, 29 Dec 2005 12:00:29 +0000 (12:00 +0000)
committerehofman <ehofman>
Thu, 29 Dec 2005 12:00:29 +0000 (12:00 +0000)
Add the basic infrastructure for a reference counter class.
Adding it now (without using it) enables Mathias and others to
prepare some memory reduction code.

simgear/structure/Makefile.am
simgear/structure/SGReferenced.hxx [new file with mode: 0644]
simgear/structure/SGSharedPtr.hxx [new file with mode: 0644]
simgear/structure/ssgSharedPtr.hxx [new file with mode: 0644]

index 386c9d94af901a1376ff2fe945a8b32c47501ef4..e7d361ae5bf94406e880b20f23f50688367763a3 100644 (file)
@@ -7,7 +7,10 @@ include_HEADERS = \
        commands.hxx \
        exception.hxx \
        event_mgr.hxx \
-       subsystem_mgr.hxx
+       ssgSharedPtr.hxx \
+       subsystem_mgr.hxx \
+       SGReferenced.hxx \
+       SGSharedPtr.hxx
 
 libsgstructure_a_SOURCES = \
        commands.cxx \
diff --git a/simgear/structure/SGReferenced.hxx b/simgear/structure/SGReferenced.hxx
new file mode 100644 (file)
index 0000000..003536a
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2005-2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef SGReferenced_HXX
+#define SGReferenced_HXX
+
+/// Base class for all reference counted SimGear objects
+/// Classes derived from this one are meant to be managed with
+/// the SGSharedPtr class.
+/// For more info see @SGSharedPtr.
+
+class SGReferenced {
+public:
+  SGReferenced(void) : _refcount(0u)
+  {}
+  /// Do not copy reference counts. Each new object has it's own counter
+  SGReferenced(const SGReferenced&) : _refcount(0u)
+  {}
+  /// Do not copy reference counts. Each object has it's own counter
+  SGReferenced& operator=(const SGReferenced&)
+  { return *this; }
+
+  static unsigned get(const SGReferenced* ref)
+  { if (ref) return ++(ref->_refcount); else return ~0u; }
+  static unsigned put(const SGReferenced* ref)
+  { if (ref) return --(ref->_refcount); else return ~0u; }
+  static unsigned count(const SGReferenced* ref)
+  { if (ref) return ref->_refcount; else return ~0u; }
+  static bool shared(const SGReferenced* ref)
+  { if (ref) return 1u < ref->_refcount; else return false; }
+
+private:
+  mutable unsigned _refcount;
+};
+
+#endif
diff --git a/simgear/structure/SGSharedPtr.hxx b/simgear/structure/SGSharedPtr.hxx
new file mode 100644 (file)
index 0000000..6b7c09d
--- /dev/null
@@ -0,0 +1,99 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2005-2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef SGSharedPtr_HXX
+#define SGSharedPtr_HXX
+
+#include "SGReferenced.hxx"
+
+/// 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.
+/// 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
+/// class pointer.
+/// One thing you need to avoid are cyclic loops with such pointers.
+/// As long as such a cyclic loop exists the reference count never drops
+/// 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.
+/// 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 SGSharedPtr {
+public:
+  SGSharedPtr(void) : _ptr(0)
+  {}
+  SGSharedPtr(T* ptr) : _ptr(ptr)
+  { get(_ptr); }
+  SGSharedPtr(const SGSharedPtr& p) : _ptr(p.ptr())
+  { get(_ptr); }
+  template<typename U>
+  SGSharedPtr(const SGSharedPtr<U>& p) : _ptr(p.ptr())
+  { get(_ptr); }
+  ~SGSharedPtr(void)
+  { put(); }
+  
+  SGSharedPtr& operator=(const SGSharedPtr& p)
+  { assign(p.ptr()); return *this; }
+  template<typename U>
+  SGSharedPtr& operator=(const SGSharedPtr<U>& p)
+  { assign(p.ptr()); return *this; }
+  template<typename U>
+  SGSharedPtr& operator=(U* p)
+  { assign(p); return *this; }
+
+  T* operator->(void) const
+  { return _ptr; }
+  T& operator*(void) const
+  { return *_ptr; }
+  operator T*(void) const
+  { return _ptr; }
+  T* ptr(void) const
+  { return _ptr; }
+
+  bool isShared(void) const
+  { return SGReferenced::shared(_ptr); }
+  unsigned getNumRefs(void) const
+  { return SGReferenced::count(_ptr); }
+
+  bool valid(void) const
+  { return _ptr; }
+
+private:
+  void assign(T* p)
+  { get(p); put(); _ptr = p; }
+
+  void get(const T* p) const
+  { SGReferenced::get(p); }
+  void put(void)
+  { if (!SGReferenced::put(_ptr)) { delete _ptr; _ptr = 0; } }
+  
+  // The reference itself.
+  T* _ptr;
+};
+
+#endif
diff --git a/simgear/structure/ssgSharedPtr.hxx b/simgear/structure/ssgSharedPtr.hxx
new file mode 100644 (file)
index 0000000..87dae7e
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2005-2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef ssgSharedPtr_HXX
+#define ssgSharedPtr_HXX
+
+/// This class is a pointer proxy doing reference counting on the object
+/// it is pointing to.
+/// It is very similar to the SGSharedPtr class but is made to work together
+/// with reference counting of plib's ssg reference counters
+/// For notes on usage see SGSharedPtr.
+
+template<typename T>
+class ssgSharedPtr {
+public:
+  ssgSharedPtr(void) : _ptr(0)
+  {}
+  ssgSharedPtr(T* ptr) : _ptr(ptr)
+  { get(_ptr); }
+  ssgSharedPtr(const ssgSharedPtr& p) : _ptr(p.ptr())
+  { get(_ptr); }
+  template<typename U>
+  ssgSharedPtr(const ssgSharedPtr<U>& p) : _ptr(p.ptr())
+  { get(_ptr); }
+  ~ssgSharedPtr(void)
+  { put(); }
+  
+  ssgSharedPtr& operator=(const ssgSharedPtr& p)
+  { assign(p.ptr()); return *this; }
+  template<typename U>
+  ssgSharedPtr& operator=(const ssgSharedPtr<U>& p)
+  { assign(p.ptr()); return *this; }
+  template<typename U>
+  ssgSharedPtr& operator=(U* p)
+  { assign(p); return *this; }
+
+  T* operator->(void) const
+  { return _ptr; }
+  T& operator*(void) const
+  { return *_ptr; }
+  operator T*(void) const
+  { return _ptr; }
+  T* ptr(void) const
+  { return _ptr; }
+
+  bool isShared(void) const
+  { if (_ptr) return 1 < _ptr->getRef(); else return false; }
+  unsigned getNumRefs(void) const
+  { if (_ptr) return _ptr->getRef(); else return 0; }
+
+  bool valid(void) const
+  { return _ptr; }
+
+private:
+  void assign(T* p)
+  { get(p); put(); _ptr = p; }
+
+  static void get(T* p)
+  { if (p) p->ref(); }
+  void put(void)
+  {
+    if (!_ptr)
+      return;
+
+    assert(0 < _ptr->getRef());
+    _ptr->deRef();
+    if (_ptr->getRef() == 0) {
+      delete _ptr;
+      _ptr = 0;
+    }
+  }
+  
+  // The reference itself.
+  T* _ptr;
+};
+
+#endif