/* This file is part of the KDE project * * Copyright (C) 2004 Koos Vriezen * * 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; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, * Boston, MA 02110-1301, USA. * * until boost gets common, a more or less compatable one .. */ #ifndef _SHAREDPTR_H_ #define _SHAREDPTR_H_ //#define SHAREDPTR_DEBUG #ifdef SHAREDPTR_DEBUG extern int shared_data_count; #include #endif namespace KMPlayer { /** * Shared data for SharedPtr and WeakPtr objects. **/ template struct SharedData { SharedData (T * t, bool w) : use_count (w?0:1), weak_count (1), ptr (t) { #ifdef SHAREDPTR_DEBUG std::cerr << "SharedData::SharedData use:" << use_count << " weak:" << weak_count << " total:" << ++shared_data_count << std::endl; #endif } #ifdef SHAREDPTR_DEBUG ~SharedData () { std::cerr << "SharedData::~SharedData" << " total:" << --shared_data_count << std::endl; } #endif void addRef (); void addWeakRef (); void release (); void releaseWeak (); void dispose (); int use_count; int weak_count; T * ptr; }; template inline void SharedData::addRef () { use_count++; weak_count++; #ifdef SHAREDPTR_DEBUG std::cerr << "SharedData::addRef use:" << use_count << " weak:" << weak_count << std::endl; #endif } template inline void SharedData::addWeakRef () { weak_count++; #ifdef SHAREDPTR_DEBUG std::cerr << "SharedData::addWeakRef use:" << use_count << " weak:" << weak_count << std::endl; #endif } template inline void SharedData::releaseWeak () { ASSERT (weak_count > 0 && weak_count > use_count); #ifdef SHAREDPTR_DEBUG std::cerr << "SharedData::releaseWeak use:" << use_count << " weak:" << weak_count-1 << std::endl; #endif if (--weak_count <= 0) delete this; } template inline void SharedData::release () { ASSERT (use_count > 0); if (--use_count <= 0) dispose (); #ifdef SHAREDPTR_DEBUG std::cerr << "SharedData::release use:" << use_count << " weak:" << weak_count << std::endl; #endif releaseWeak (); } template inline void SharedData::dispose () { ASSERT (use_count == 0); #ifdef SHAREDPTR_DEBUG std::cerr << "SharedData::dispose use:" << use_count << " weak:" << weak_count << std::endl; #endif delete ptr; ptr = 0; } template struct WeakPtr; /** * Shared class based on boost shared * This makes it possible to share pointers w/o having to worry about * memory leaks. A pointer gets deleted as soon as the last Shared pointer * gets destroyed. As such, never use (or be extremely carefull) not to * use pointers or references to shared objects **/ template struct SharedPtr { SharedPtr () : data (0L) {}; SharedPtr (T *t) : data (t ? new SharedData (t, false) : 0L) {} SharedPtr (const SharedPtr & s) : data (s.data) { if (data) data->addRef (); } SharedPtr (const WeakPtr &); ~SharedPtr () { if (data) data->release (); } SharedPtr & operator = (const SharedPtr &); SharedPtr & operator = (const WeakPtr &); SharedPtr & operator = (T *); T * ptr () const { return data ? data->ptr : 0L; } T * operator -> () { return data ? data->ptr : 0L; } T * operator -> () const { return data ? data->ptr : 0L; } T & operator * () { return *data->ptr; } const T & operator * () const { return *data->ptr; } // operator bool () const { return data && data->ptr; } bool operator == (const SharedPtr & s) const { return data == s.data; } bool operator == (const WeakPtr & w) const; bool operator == (const T * t) const { return (!t && !data) || (data && data->ptr == t); } bool operator == (T * t) const { return (!t && !data) || (data && data->ptr == t); } bool operator != (const SharedPtr & s) const { return data != s.data; } bool operator != (const WeakPtr & w) const; bool operator != (const T * t) const { return !operator == (t); } operator T * () { return data ? data->ptr : 0L; } operator const T * () const { return data ? data->ptr : 0L; } mutable SharedData * data; }; template bool operator == (T * t, SharedPtr & s) { return (!t && !s.data) || (s.data && s.data->ptr == t); } template bool operator == (const T * t, SharedPtr & s) { return (!t && !s.data) || (s.data && s.data->ptr == t); } template inline SharedPtr & SharedPtr::operator = (const SharedPtr & s) { if (data != s.data) { SharedData * tmp = data; data = s.data; if (data) data->addRef (); if (tmp) tmp->release (); } return *this; } template inline SharedPtr & SharedPtr::operator = (T * t) { if ((!data && t) || (data && data->ptr != t)) { if (data) data->release (); data = t ? new SharedData (t, false) : 0L; } return *this; } /** * Weak version of SharedPtr. This will also have access to the SharedData * pointer, only these object wont prevent destruction of the shared * pointer, hence weak references */ template struct WeakPtr { WeakPtr () : data (0L) {}; WeakPtr (T * t) : data (t ? new SharedData (t, true) : 0) {} WeakPtr (T * t, bool /*b*/) : data (t ? new SharedData (t, true) : 0) {} WeakPtr (const WeakPtr & s) : data (s.data) { if (data) data->addWeakRef (); } WeakPtr (const SharedPtr & s) : data (s.data) { if (data) data->addWeakRef (); } ~WeakPtr () { if (data) data->releaseWeak (); } WeakPtr & operator = (const WeakPtr &); WeakPtr & operator = (const SharedPtr &); WeakPtr & operator = (T *); T * ptr () const { return data ? data->ptr : 0L; } T * operator -> () { return data ? data->ptr : 0L; } const T * operator -> () const { return data ? data->ptr : 0L; } T & operator * () { return *data->ptr; } const T & operator * () const { return *data->ptr; } // operator bool () const { return data && !!data->ptr; } bool operator == (const WeakPtr & w) const { return data == w.data; } bool operator == (const SharedPtr & s) const { return data == s.data; } bool operator == (const T * t) const { return (!t && !data) || (data && data->ptr == t); } bool operator == (T * t) const { return (!t && !data) || (data && data->ptr == t); } bool operator != (const WeakPtr & w) const { return data != w.data; } bool operator != (const SharedPtr & s) const { return data != s.data; } operator T * () { return data ? data->ptr : 0L; } operator const T * () const { return data ? data->ptr : 0L; } mutable SharedData * data; }; template bool operator == (T * t, WeakPtr & s) { return (!t && !s.data) || (s.data && s.data->ptr == t); } template bool operator == (const T * t, WeakPtr & s) { return (!t && !s.data) || (s.data && s.data->ptr == t); } template inline WeakPtr & WeakPtr::operator = (const WeakPtr & w) { if (data != w.data) { SharedData * tmp = data; data = w.data; if (data) data->addWeakRef (); if (tmp) tmp->releaseWeak (); } return *this; } template inline WeakPtr & WeakPtr::operator = (const SharedPtr & s) { if (data != s.data) { SharedData * tmp = data; data = s.data; if (data) data->addWeakRef (); if (tmp) tmp->releaseWeak (); } return *this; } template inline WeakPtr & WeakPtr::operator = (T * t) { if (data) data->releaseWeak (); data = t ? new SharedData (t, true) : 0L; return *this; } template inline SharedPtr::SharedPtr (const WeakPtr & w) : data (w.data) { if (data) data->addRef (); } template inline SharedPtr & SharedPtr::operator = (const WeakPtr & s) { if (data != s.data) { SharedData * tmp = data; data = s.data; if (data) data->addRef (); if (tmp) tmp->release (); } return *this; } template inline bool SharedPtr::operator == (const WeakPtr & w) const { return data == w.data; } template inline bool SharedPtr::operator != (const WeakPtr & w) const { return data != w.data; } } #endif