File indexing completed on 2024-04-21 15:38:21

0001 /* This file is part of the KDE project
0002  *
0003  * Copyright (C) 2004 Koos Vriezen <koos.vriezen@xs4all.nl>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  *
0020  * until boost gets common, a more or less compatable one ..
0021  */
0022 
0023 #ifndef _SHAREDPTR_H_
0024 #define _SHAREDPTR_H_
0025 
0026 //#define SHAREDPTR_DEBUG
0027 
0028 #ifdef SHAREDPTR_DEBUG
0029 extern int shared_data_count;
0030 #include <iostream>
0031 #endif
0032 
0033 #include "kmplayer_def.h"
0034 
0035 namespace KMPlayer {
0036 
0037 class KMPLAYER_EXPORT CacheAllocator {
0038     void **pool;
0039     size_t size;
0040     int count;
0041 public:
0042     CacheAllocator (size_t s);
0043 
0044     void *alloc ();
0045     void dealloc (void *p);
0046 };
0047 
0048 extern CacheAllocator *shared_data_cache_allocator;
0049 
0050 /**
0051  *  Shared data for SharedPtr and WeakPtr objects.
0052  **/
0053 template <class T>
0054 struct SharedData {
0055     SharedData (T * t, bool w) : use_count (w?0:1), weak_count (1), ptr (t) {
0056 #ifdef SHAREDPTR_DEBUG
0057     std::cerr << "SharedData::SharedData use:" << use_count << " weak:" << weak_count << " total:" << ++shared_data_count << std::endl;
0058 #endif
0059     }
0060 #ifdef SHAREDPTR_DEBUG
0061     ~SharedData () { std::cerr << "SharedData::~SharedData" << " total:" << --shared_data_count << std::endl; }
0062 #endif
0063     static void *operator new (size_t);
0064     static void operator delete (void *);
0065     void addRef ();
0066     void addWeakRef ();
0067     void release ();
0068     void releaseWeak ();
0069     void dispose ();
0070     int use_count;
0071     int weak_count;
0072     T * ptr;
0073 };
0074 
0075 template <class T> inline void *SharedData<T>::operator new (size_t s) {
0076     if (!shared_data_cache_allocator)
0077         shared_data_cache_allocator = new CacheAllocator (s);
0078     return shared_data_cache_allocator->alloc ();
0079 }
0080 
0081 template <class T> inline void SharedData<T>::operator delete (void *p) {
0082     shared_data_cache_allocator->dealloc (p);
0083 }
0084 
0085 template <class T> inline void SharedData<T>::addRef () {
0086     use_count++;
0087     weak_count++;
0088 #ifdef SHAREDPTR_DEBUG
0089     std::cerr << "SharedData::addRef use:" << use_count << " weak:" << weak_count << std::endl;
0090 #endif
0091 }
0092 
0093 template <class T> inline void SharedData<T>::addWeakRef () {
0094     weak_count++;
0095 #ifdef SHAREDPTR_DEBUG
0096     std::cerr << "SharedData::addWeakRef use:" << use_count << " weak:" << weak_count << std::endl;
0097 #endif
0098 }
0099 
0100 template <class T> inline void SharedData<T>::releaseWeak () {
0101     ASSERT (weak_count > 0 && weak_count > use_count);
0102 #ifdef SHAREDPTR_DEBUG
0103     std::cerr << "SharedData::releaseWeak use:" << use_count << " weak:" << weak_count-1 << std::endl;
0104 #endif
0105     if (--weak_count <= 0) delete this;
0106 }
0107 
0108 template <class T> inline void SharedData<T>::release () {
0109     ASSERT (use_count > 0);
0110     if (--use_count <= 0) dispose (); 
0111 #ifdef SHAREDPTR_DEBUG
0112     std::cerr << "SharedData::release use:" << use_count << " weak:" << weak_count << std::endl;
0113 #endif
0114     releaseWeak ();
0115 }
0116 
0117 template <class T> inline void SharedData<T>::dispose () {
0118     ASSERT (use_count == 0);
0119 #ifdef SHAREDPTR_DEBUG
0120     std::cerr << "SharedData::dispose use:" << use_count << " weak:" << weak_count << std::endl;
0121 #endif
0122     T *p = ptr;
0123     ptr = NULL;
0124     delete p;
0125 }
0126 
0127 template <class T> struct WeakPtr;
0128 
0129 /**
0130  * Shared class based on boost shared
0131  * This makes it possible to share pointers w/o having to worry about
0132  * memory leaks. A pointer gets deleted as soon as the last Shared pointer
0133  * gets destroyed. As such, never use (or be extremely carefull) not to
0134  * use pointers or references to shared objects
0135  **/
0136 template <class T>
0137 struct SharedPtr {
0138     SharedPtr () : data (0L) {};
0139     SharedPtr (T *t) : data (t ? new SharedData<T> (t, false) : 0L) {}
0140     SharedPtr (const SharedPtr<T> & s) : data (s.data) { if (data) data->addRef (); }
0141     SharedPtr (const WeakPtr <T> &);
0142     ~SharedPtr () { if (data) data->release (); }
0143     SharedPtr<T> & operator = (const SharedPtr<T> &);
0144     SharedPtr<T> & operator = (const WeakPtr<T> &);
0145     SharedPtr<T> & operator = (T *);
0146     T * ptr () const { return data ? data->ptr : 0L; }
0147     T * operator -> () { return data ? data->ptr : 0L; }
0148     T * operator -> () const { return data ? data->ptr : 0L; }
0149     T & operator * () { return *data->ptr; }
0150     const T & operator * () const { return *data->ptr; }
0151     // operator bool () const { return data && data->ptr; }
0152     bool operator == (const SharedPtr<T> & s) const { return data == s.data; }
0153     bool operator == (const WeakPtr<T> & w) const;
0154     bool operator == (const T * t) const { return (!t && !data) || (data && data->ptr == t); }
0155     bool operator == (T * t) const { return (!t && !data) || (data && data->ptr == t); }
0156     bool operator != (const SharedPtr<T> & s) const { return data != s.data; }
0157     bool operator != (const WeakPtr<T> & w) const;
0158     bool operator != (const T * t) const { return !operator == (t); }
0159     operator T * () { return data ? data->ptr : 0L; }
0160     operator const T * () const { return data ? data->ptr : 0L; }
0161     mutable SharedData<T> * data;
0162 };
0163 
0164 template <class T>
0165 bool operator == (T * t, SharedPtr <T> & s) {
0166     return (!t && !s.data) || (s.data && s.data->ptr == t);
0167 }
0168 
0169 template <class T>
0170 bool operator == (const T * t, SharedPtr <T> & s) {
0171     return (!t && !s.data) || (s.data && s.data->ptr == t);
0172 }
0173 
0174 template <class T>
0175 inline SharedPtr<T> & SharedPtr<T>::operator = (const SharedPtr<T> & s) {
0176     if (data != s.data) {
0177         SharedData<T> * tmp = data;
0178         data = s.data;
0179         if (data) data->addRef ();
0180         if (tmp) tmp->release ();
0181     }
0182     return *this;
0183 }
0184 
0185 template <class T> inline SharedPtr<T> & SharedPtr<T>::operator = (T * t) {
0186     if ((!data && t) || (data && data->ptr != t)) {
0187         if (data) data->release ();
0188         data = t ? new SharedData<T> (t, false) : 0L;
0189     }
0190     return *this;
0191 }
0192 
0193 /**
0194  * Weak version of SharedPtr. This will also have access to the SharedData
0195  * pointer, only these object wont prevent destruction of the shared
0196  * pointer, hence weak references
0197  */
0198 template <class T>
0199 struct WeakPtr {
0200     WeakPtr () : data (0L) {};
0201     WeakPtr (T * t) : data (t ? new SharedData<T> (t, true) : 0) {}
0202     WeakPtr (T * t, bool /*b*/) : data (t ? new SharedData<T> (t, true) : 0) {}
0203     WeakPtr (const WeakPtr<T> & s) : data (s.data) { if (data) data->addWeakRef (); }
0204     WeakPtr (const SharedPtr<T> & s) : data (s.data) { if (data) data->addWeakRef (); }
0205     ~WeakPtr () { if (data) data->releaseWeak (); }
0206     WeakPtr<T> & operator = (const WeakPtr<T> &);
0207     WeakPtr<T> & operator = (const SharedPtr<T> &);
0208     WeakPtr<T> & operator = (T *);
0209     T * ptr () const { return data ? data->ptr : 0L; }
0210     T * operator -> () { return data ? data->ptr : 0L; }
0211     const T * operator -> () const { return data ? data->ptr : 0L; }
0212     T & operator * () { return *data->ptr; }
0213     const T & operator * () const { return *data->ptr; }
0214     // operator bool () const { return data && !!data->ptr; }
0215     bool operator == (const WeakPtr<T> & w) const { return data == w.data; }
0216     bool operator == (const SharedPtr<T> & s) const { return data == s.data; }
0217     bool operator == (const T * t) const { return (!t && !data) || (data && data->ptr == t); }
0218     bool operator == (T * t) const { return (!t && !data) || (data && data->ptr == t); }
0219     bool operator != (const WeakPtr<T> & w) const { return data != w.data; }
0220     bool operator != (const SharedPtr<T> & s) const { return data != s.data; }
0221     operator T * () { return data ? data->ptr : 0L; }
0222     operator const T * () const { return data ? data->ptr : 0L; }
0223     mutable SharedData<T> * data;
0224 };
0225 
0226 template <class T>
0227 bool operator == (T * t, WeakPtr <T> & s) {
0228     return (!t && !s.data) || (s.data && s.data->ptr == t);
0229 }
0230 
0231 template <class T>
0232 bool operator == (const T * t, WeakPtr <T> & s) {
0233     return (!t && !s.data) || (s.data && s.data->ptr == t);
0234 }
0235 
0236 template <class T>
0237 inline WeakPtr<T> & WeakPtr<T>::operator = (const WeakPtr<T> & w) {
0238     if (data != w.data) {
0239         SharedData<T> * tmp = data;
0240         data = w.data;
0241         if (data) data->addWeakRef ();
0242         if (tmp) tmp->releaseWeak ();
0243     }
0244     return *this;
0245 }
0246 
0247 template <class T>
0248 inline WeakPtr<T> & WeakPtr<T>::operator = (const SharedPtr<T> & s) {
0249     if (data != s.data) {
0250         SharedData<T> * tmp = data;
0251         data = s.data;
0252         if (data) data->addWeakRef ();
0253         if (tmp) tmp->releaseWeak ();
0254     }
0255     return *this;
0256 }
0257 
0258 template <class T>
0259 inline WeakPtr<T> & WeakPtr<T>::operator = (T * t) {
0260     if (data) data->releaseWeak ();
0261     data = t ? new SharedData<T> (t, true) : 0L;
0262     return *this;
0263 }
0264 
0265 template <class T> inline SharedPtr<T>::SharedPtr (const WeakPtr <T> & w) : data (w.data) {
0266     if (data) data->addRef ();
0267 }
0268 
0269 template <class T>
0270 inline SharedPtr<T> & SharedPtr<T>::operator = (const WeakPtr<T> & s) {
0271     if (data != s.data) {
0272         SharedData<T> * tmp = data;
0273         data = s.data;
0274         if (data) data->addRef ();
0275         if (tmp) tmp->release ();
0276     }
0277     return *this;
0278 }
0279 
0280 template <class T>
0281 inline  bool SharedPtr<T>::operator == (const WeakPtr<T> & w) const {
0282     return data == w.data;
0283 }
0284 
0285 template <class T>
0286 inline  bool SharedPtr<T>::operator != (const WeakPtr<T> & w) const {
0287     return data != w.data;
0288 }
0289 
0290 }
0291 
0292 #endif