You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
8.8 KiB
265 lines
8.8 KiB
/* This file is part of the KDE project
|
|
*
|
|
* Copyright (C) 2004 Koos Vriezen <koos.vriezen@xs4all.nl>
|
|
*
|
|
* 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
|