File indexing completed on 2024-04-21 04:54:10

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