File indexing completed on 2024-05-05 09:08:13
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