File indexing completed on 2024-12-22 04:17:22
0001 /* This file is derived from the KDE libraries 0002 Copyright (c) 1999 Waldo Bastian <bastian@kde.org> 0003 Copyright (c) 2004 The University of Toronto <netterfield@astro.utoronto.ca> 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 version 2 as published by the Free Software Foundation. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 */ 0014 #ifndef SharedPTR_H 0015 #define SharedPTR_H 0016 0017 #include <QSemaphore> 0018 #include <QDebug> 0019 0020 //#define KST_DEBUG_SHARED 0021 #ifdef KST_DEBUG_SHARED 0022 #define KST_DBG if (true) 0023 #else 0024 #define KST_DBG if (false) 0025 #endif 0026 0027 // NOTE: In order to preserve binary compatibility with plugins, you must 0028 // not add, remove, or change member variables or virtual functions. 0029 // You must also not remove or change non-virtual functions. 0030 0031 // See KSharedPtr in KDE libraries for more information 0032 0033 namespace Kst { 0034 0035 #define SEMAPHORE_COUNT 999999 0036 0037 class Shared { 0038 public: 0039 /** 0040 * Standard constructor. This will initialize the reference count 0041 * on this object to 0. 0042 */ 0043 Shared() : sem(SEMAPHORE_COUNT) { } 0044 0045 /** 0046 * Copy constructor. This will @em not actually copy the objects 0047 * but it will initialize the reference count on this object to 0. 0048 */ 0049 Shared( const Shared & ) : sem(SEMAPHORE_COUNT) { } 0050 0051 /** 0052 * Overloaded assignment operator. 0053 */ 0054 Shared &operator=(const Shared & ) { return *this; } 0055 0056 /** 0057 * Increases the reference count by one. 0058 */ 0059 void _KShared_ref() const { 0060 sem.acquire(1); 0061 KST_DBG qDebug() << "KShared_ref: " << (void*)this << " -> " << _KShared_count() << endl; 0062 } 0063 0064 /** 0065 * Releases a reference (decreases the reference count by one). If 0066 * the count goes to 0, this object will delete itself. 0067 */ 0068 void _KShared_unref() const { 0069 sem.release(1); 0070 KST_DBG qDebug() << "KShared_unref: " << (void*)this << " -> " << _KShared_count() << endl; 0071 if (SEMAPHORE_COUNT == sem.available()) delete this; 0072 } 0073 0074 /** 0075 * Return the current number of references held. 0076 * 0077 * @return Number of references 0078 */ 0079 int _KShared_count() const { return SEMAPHORE_COUNT - sem.available(); } 0080 0081 protected: 0082 virtual ~Shared() { } 0083 0084 private: 0085 mutable QSemaphore sem; 0086 }; 0087 0088 0089 template< class T > 0090 struct SharedPtr 0091 { 0092 public: 0093 /** 0094 * Creates a null pointer. 0095 */ 0096 SharedPtr() : ptr(0) { isPtrValid(); } 0097 0098 /** 0099 * Creates a new pointer. 0100 * @param t the pointer 0101 */ 0102 SharedPtr( T* t ) : ptr(t) { if (isPtrValid()) ptr->_KShared_ref(); } 0103 0104 /** 0105 * Copies a pointer. 0106 * @param p the pointer to copy 0107 */ 0108 SharedPtr( const SharedPtr& p ) 0109 : ptr(p.ptr) { if (isPtrValid()) ptr->_KShared_ref(); } 0110 0111 template<class Y> SharedPtr(SharedPtr<Y>& p) 0112 : ptr(p.data()) { if (isPtrValid()) ptr->_KShared_ref(); } 0113 0114 /** 0115 * Unreferences the object that this pointer points to. If it was 0116 * the last reference, the object will be deleted. 0117 */ 0118 ~SharedPtr() { if (isPtrValid()) ptr->_KShared_unref(); } 0119 0120 SharedPtr<T>& operator= ( const SharedPtr<T>& p ) { 0121 isPtrValid(); 0122 if ( ptr == p.ptr ) return *this; 0123 if (isPtrValid()) ptr->_KShared_unref(); 0124 ptr = p.ptr; 0125 if (isPtrValid()) ptr->_KShared_ref(); 0126 return *this; 0127 } 0128 0129 template<class Y> 0130 SharedPtr<T>& operator=(SharedPtr<Y>& p) { 0131 isPtrValid(); 0132 if (ptr == p.data()) return *this; 0133 if (isPtrValid()) ptr->_KShared_unref(); 0134 ptr = p.data(); 0135 if (isPtrValid()) ptr->_KShared_ref(); 0136 return *this; 0137 } 0138 0139 SharedPtr<T>& operator= ( T* p ) { 0140 isPtrValid(); 0141 if (ptr == p) return *this; 0142 if (isPtrValid()) ptr->_KShared_unref(); 0143 ptr = p; 0144 if (isPtrValid()) ptr->_KShared_ref(); 0145 return *this; 0146 } 0147 0148 bool operator== ( const SharedPtr<T>& p ) const { isPtrValid(); return ( ptr == p.ptr ); } 0149 bool operator!= ( const SharedPtr<T>& p ) const { isPtrValid(); return ( ptr != p.ptr ); } 0150 bool operator== ( const T* p ) const { isPtrValid(); return ( ptr == p ); } 0151 bool operator!= ( const T* p ) const { isPtrValid(); return ( ptr != p ); } 0152 bool operator!() const { isPtrValid(); return ( ptr == 0 ); } 0153 operator T*() const { isPtrValid(); return ptr; } 0154 0155 /** 0156 * Returns the pointer. 0157 * @return the pointer 0158 */ 0159 T* data() { isPtrValid(); return ptr; } 0160 0161 /** 0162 * Returns the pointer. 0163 * @return the pointer 0164 */ 0165 const T* data() const { isPtrValid(); return ptr; } 0166 0167 const T& operator*() const { Q_ASSERT(isPtrValid()); return *ptr; } 0168 T& operator*() { Q_ASSERT(isPtrValid()); return *ptr; } 0169 const T* operator->() const { Q_ASSERT(isPtrValid()); return ptr; } 0170 T* operator->() { Q_ASSERT(isPtrValid()); return ptr; } 0171 0172 /** 0173 * Returns the number of references. 0174 * @return the number of references 0175 */ 0176 int count() const { Q_ASSERT(isPtrValid()); return ptr->_KShared_count(); } // for debugging purposes 0177 0178 0179 bool isPtrValid() const { return ptr != 0; } 0180 0181 private: 0182 T* ptr; 0183 }; 0184 0185 0186 template <typename T, typename U> 0187 inline SharedPtr<T> kst_cast(SharedPtr<U> object) { 0188 return qobject_cast<T*>(object.data()); 0189 } 0190 0191 // FIXME: make this safe 0192 template <typename T> 0193 inline SharedPtr<T> kst_cast(QObject *object) { 0194 return qobject_cast<T*>(object); 0195 } 0196 0197 } 0198 #endif