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.
commands.hxx \
exception.hxx \
event_mgr.hxx \
- subsystem_mgr.hxx
+ ssgSharedPtr.hxx \
+ subsystem_mgr.hxx \
+ SGReferenced.hxx \
+ SGSharedPtr.hxx
libsgstructure_a_SOURCES = \
commands.cxx \
--- /dev/null
+/* -*-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
--- /dev/null
+/* -*-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
--- /dev/null
+/* -*-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