diff options
Diffstat (limited to 'src/common/util/CountedPtr.h')
-rw-r--r-- | src/common/util/CountedPtr.h | 222 |
1 files changed, 21 insertions, 201 deletions
diff --git a/src/common/util/CountedPtr.h b/src/common/util/CountedPtr.h index e3f34ec2..81604e45 100644 --- a/src/common/util/CountedPtr.h +++ b/src/common/util/CountedPtr.h @@ -21,219 +21,39 @@ #include <cassert> #include <cstddef> -// honestly, WTF? -#include <boost/shared_ptr.hpp> - -#define CountedPtr boost::shared_ptr -#define PtrCast boost::dynamic_pointer_cast -#if 0 -// FIXME -#ifndef NDEBUG -#define COUNTED_PTR_DEBUG +#ifdef DEBUG +#define BOOST_SP_ENABLE_DEBUG_HOOKS 1 #include <iostream> #include <list> #include <algorithm> -static std::list<void*> counted_ptr_counters; -#endif +static std::list<void*> counted_ptr_counters; -/** Simple reference counted pointer. - * - * Allocates one counter on the heap on initial construction. You can safely - * cast a CountedPtr<X> to a CountedPtr<Y> iff Y is a base of X (eg the cast - * will only compile if it is a valid up-cast). - * - * It is possible for this to be a NULL pointer, and a boolean conversion - * operator is provided so you can test for this with "if (someCountedPtr)". - * Dereferencing a NULL CountedPtr will result in a failed assertion if - * debugging is enabled. - * - * FIXME: test this more thoroughly - */ -template <class T> -class CountedPtr -{ -public: +// Use debug hooks to ensure 2 shared_ptrs never point to the same thing +namespace boost { - // Declare some other type of CountedPtr as a friend (for casting) - template <class Y> friend class CountedPtr; - - - /** Allocate a new Counter (if p is non-NULL) */ - CountedPtr(T* p) - : _counter(0) - { - if (p) - _counter = new Counter(p); - } - - /** Make a NULL CountedPtr. - * It would be best if this didn't exist, but it makes these storable - * in STL containers :/ - */ - CountedPtr() - : _counter(0) - {} - - ~CountedPtr() - { - release(); - } - - /** Copy a CountedPtr with the same type. */ - CountedPtr(const CountedPtr& copy) - : _counter(0) - { - assert(this != ©); - - if (copy) - retain(copy._counter); - - assert(_counter == copy._counter); + static void sp_scalar_constructor_hook(void* object, unsigned long cnt, void* ptr) { + assert(std::find(counted_ptr_counters.begin(), counted_ptr_counters.end(), + (void*)object) == counted_ptr_counters.end()); + counted_ptr_counters.push_back(object); + //std::cerr << "Creating " << typeid(object).name() << " Pointer to " + //<< object << std::endl; } - /** Copy a CountedPtr to a valid base class. - */ - template <class Y> - CountedPtr(const CountedPtr<Y>& y) - : _counter(0) - { - assert(this != (CountedPtr*)&y); - - // Fail if this is not a valid cast - if (y) { - T* const casted_y = dynamic_cast<T* const>(y._counter->ptr); - - if (casted_y) { - //release(); // FIXME: leak? - retain((Counter*)y._counter); - assert(_counter == (Counter*)y._counter); - } - } - - assert( ! _counter || _counter == (Counter*)y._counter); + static void sp_scalar_destructor_hook(void* object, unsigned long cnt, void* ptr) { + counted_ptr_counters.remove(object); + //std::cerr << "Destroying " << typeid(object).name() << " Pointer to " + //<< object << std::endl; } - /** Assign to the value of a CountedPtr of the same type. */ - CountedPtr& operator=(const CountedPtr& copy) - { - if (this != ©) { - assert( ! _counter || _counter != copy._counter); - release(); - retain(copy._counter); - } - assert(_counter == copy._counter); - return *this; - } +} +#endif // DEBUG - /** Assign to the value of a CountedPtr of a different type. */ - template <class Y> - CountedPtr& operator=(const CountedPtr<Y>& y) - { - if (this != (CountedPtr*)&y) { - assert(_counter != y._counter); - release(); - retain(y._counter); - } - assert(_counter == y._counter); - return *this; - } - - inline bool operator==(const CountedPtr& p) const - { - return (_counter == p._counter); - } - inline bool operator!=(const CountedPtr& p) const - { - return (_counter != p._counter); - } - - /** Allow testing for NULL nicely like a real pointer */ - operator bool() const - { - return (_counter && _counter->ptr); - } - - inline T& operator*() const - { - assert(_counter); - assert(_counter->count > 0); - assert(_counter->ptr); - return *_counter->ptr; - } - - inline T* operator->() const - { - assert(_counter); - assert(_counter->count > 0); - assert(_counter->ptr); - return _counter->ptr; - } - - inline T* get() const { return _counter ? _counter->ptr : 0; } - - bool unique() const { return (_counter ? _counter->count == 1 : true); } - -private: - /** Stored on the heap and referred to by all existing CountedPtr's to - * the object */ - class Counter - { - public: - Counter(T* p) - : ptr(p) - , count(1) - { - assert(p); -#ifdef COUNTED_PTR_DEBUG - assert(std::find(counted_ptr_counters.begin(), counted_ptr_counters.end(), (void*)p) - == counted_ptr_counters.end()); - counted_ptr_counters.push_back(p); - std::cerr << "Creating " << typeid(T).name() << " Counter " << this << std::endl; -#endif - } - - ~Counter() - { - // for debugging - assert(count == 0); - count = 0; - } - - T* const ptr; - volatile size_t count; - - private: - // Prevent copies (undefined) - Counter(const Counter& copy); - Counter& operator=(const Counter& copy); - }; - - /** Increment the count */ - void retain(Counter* c) - { - assert( ! _counter || _counter == c); - _counter = c; - if (_counter) - ++(c->count); - } - - /** Decrement the count, delete if we're the last reference */ - void release() - { - if (_counter) { - if (--(_counter->count) == 0) { - delete _counter->ptr; - delete _counter; - } - _counter = 0; - } - } - +#include <boost/shared_ptr.hpp> - Counter* _counter; -}; -#endif +#define CountedPtr boost::shared_ptr +#define PtrCast boost::dynamic_pointer_cast #endif // COUNTED_PTR_H + |