diff options
Diffstat (limited to 'src/kmplayershared.h')
-rw-r--r-- | src/kmplayershared.h | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/src/kmplayershared.h b/src/kmplayershared.h new file mode 100644 index 0000000..3066b4c --- /dev/null +++ b/src/kmplayershared.h @@ -0,0 +1,264 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2004 Koos Vriezen <[email protected]> + * + * 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 <iostream> +#endif + +namespace KMPlayer { + +/** + * Shared data for SharedPtr and WeakPtr objects. + **/ +template <class T> +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 <class T> inline void SharedData<T>::addRef () { + use_count++; + weak_count++; +#ifdef SHAREDPTR_DEBUG + std::cerr << "SharedData::addRef use:" << use_count << " weak:" << weak_count << std::endl; +#endif +} + +template <class T> inline void SharedData<T>::addWeakRef () { + weak_count++; +#ifdef SHAREDPTR_DEBUG + std::cerr << "SharedData::addWeakRef use:" << use_count << " weak:" << weak_count << std::endl; +#endif +} + +template <class T> inline void SharedData<T>::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 <class T> inline void SharedData<T>::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 <class T> inline void SharedData<T>::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 <class T> 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 <class T> +struct SharedPtr { + SharedPtr () : data (0L) {}; + SharedPtr (T *t) : data (t ? new SharedData<T> (t, false) : 0L) {} + SharedPtr (const SharedPtr<T> & s) : data (s.data) { if (data) data->addRef (); } + SharedPtr (const WeakPtr <T> &); + ~SharedPtr () { if (data) data->release (); } + SharedPtr<T> & operator = (const SharedPtr<T> &); + SharedPtr<T> & operator = (const WeakPtr<T> &); + SharedPtr<T> & 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<T> & s) const { return data == s.data; } + bool operator == (const WeakPtr<T> & 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<T> & s) const { return data != s.data; } + bool operator != (const WeakPtr<T> & 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<T> * data; +}; + +template <class T> +bool operator == (T * t, SharedPtr <T> & s) { + return (!t && !s.data) || (s.data && s.data->ptr == t); +} + +template <class T> +bool operator == (const T * t, SharedPtr <T> & s) { + return (!t && !s.data) || (s.data && s.data->ptr == t); +} + +template <class T> +inline SharedPtr<T> & SharedPtr<T>::operator = (const SharedPtr<T> & s) { + if (data != s.data) { + SharedData<T> * tmp = data; + data = s.data; + if (data) data->addRef (); + if (tmp) tmp->release (); + } + return *this; +} + +template <class T> inline SharedPtr<T> & SharedPtr<T>::operator = (T * t) { + if ((!data && t) || (data && data->ptr != t)) { + if (data) data->release (); + data = t ? new SharedData<T> (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 <class T> +struct WeakPtr { + WeakPtr () : data (0L) {}; + WeakPtr (T * t) : data (t ? new SharedData<T> (t, true) : 0) {} + WeakPtr (T * t, bool /*b*/) : data (t ? new SharedData<T> (t, true) : 0) {} + WeakPtr (const WeakPtr<T> & s) : data (s.data) { if (data) data->addWeakRef (); } + WeakPtr (const SharedPtr<T> & s) : data (s.data) { if (data) data->addWeakRef (); } + ~WeakPtr () { if (data) data->releaseWeak (); } + WeakPtr<T> & operator = (const WeakPtr<T> &); + WeakPtr<T> & operator = (const SharedPtr<T> &); + WeakPtr<T> & 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<T> & w) const { return data == w.data; } + bool operator == (const SharedPtr<T> & 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<T> & w) const { return data != w.data; } + bool operator != (const SharedPtr<T> & s) const { return data != s.data; } + operator T * () { return data ? data->ptr : 0L; } + operator const T * () const { return data ? data->ptr : 0L; } + mutable SharedData<T> * data; +}; + +template <class T> +bool operator == (T * t, WeakPtr <T> & s) { + return (!t && !s.data) || (s.data && s.data->ptr == t); +} + +template <class T> +bool operator == (const T * t, WeakPtr <T> & s) { + return (!t && !s.data) || (s.data && s.data->ptr == t); +} + +template <class T> +inline WeakPtr<T> & WeakPtr<T>::operator = (const WeakPtr<T> & w) { + if (data != w.data) { + SharedData<T> * tmp = data; + data = w.data; + if (data) data->addWeakRef (); + if (tmp) tmp->releaseWeak (); + } + return *this; +} + +template <class T> +inline WeakPtr<T> & WeakPtr<T>::operator = (const SharedPtr<T> & s) { + if (data != s.data) { + SharedData<T> * tmp = data; + data = s.data; + if (data) data->addWeakRef (); + if (tmp) tmp->releaseWeak (); + } + return *this; +} + +template <class T> +inline WeakPtr<T> & WeakPtr<T>::operator = (T * t) { + if (data) data->releaseWeak (); + data = t ? new SharedData<T> (t, true) : 0L; + return *this; +} + +template <class T> inline SharedPtr<T>::SharedPtr (const WeakPtr <T> & w) : data (w.data) { + if (data) data->addRef (); +} + +template <class T> +inline SharedPtr<T> & SharedPtr<T>::operator = (const WeakPtr<T> & s) { + if (data != s.data) { + SharedData<T> * tmp = data; + data = s.data; + if (data) data->addRef (); + if (tmp) tmp->release (); + } + return *this; +} + +template <class T> +inline bool SharedPtr<T>::operator == (const WeakPtr<T> & w) const { + return data == w.data; +} + +template <class T> +inline bool SharedPtr<T>::operator != (const WeakPtr<T> & w) const { + return data != w.data; +} + +} + +#endif |