File indexing completed on 2023-09-24 04:04:54
0001 /* 0002 * This file is part of the KDE libraries. 0003 * 0004 * Copyright 2005 Frerich Raabe <raabe@kde.org> 0005 * 0006 * Redistribution and use in source and binary forms, with or without 0007 * modification, are permitted provided that the following conditions 0008 * are met: 0009 * 0010 * 1. Redistributions of source code must retain the above copyright 0011 * notice, this list of conditions and the following disclaimer. 0012 * 2. Redistributions in binary form must reproduce the above copyright 0013 * notice, this list of conditions and the following disclaimer in the 0014 * documentation and/or other materials provided with the distribution. 0015 * 0016 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 #ifndef KSHAREDPTR_H 0028 #define KSHAREDPTR_H 0029 0030 #include <kdelibs4support_export.h> 0031 0032 #include <QSharedData> 0033 0034 /** 0035 * @deprecated 0036 * Use QSharedData instead. 0037 */ 0038 typedef KDELIBS4SUPPORT_DEPRECATED QSharedData KShared; 0039 0040 /** 0041 * \class KSharedPtr ksharedptr.h <KSharedPtr> 0042 * 0043 * Can be used to control the lifetime of an object that has derived 0044 * QSharedData. As long a someone holds 0045 * a KSharedPtr on some QSharedData object it won't become deleted but 0046 * is deleted once its reference count is 0. 0047 * This struct emulates C++ pointers virtually perfectly. 0048 * So just use it like a simple C++ pointer. 0049 * 0050 * The difference with QSharedPointer is that QSharedPointer does the refcounting 0051 * in the pointer, while KSharedPtr does the refcounting in the object. 0052 * This allows to convert to a raw pointer temporarily and back to a KSharedPtr 0053 * without deleting the object, if another reference exists. But it imposes a 0054 * requirement on the object, which must inherit QSharedData. 0055 * 0056 * The difference with using QSharedDataPointer is that QSharedDataPointer is 0057 * a building block for implementing a value class with implicit sharing (like QString), 0058 * whereas KSharedPtr provides refcounting to code that uses pointers. 0059 * 0060 * @author Waldo Bastian <bastian@kde.org> 0061 * 0062 * @deprecated use QExplicitlySharedDataPointer instead 0063 * 0064 */ 0065 template< class T > 0066 class KDELIBS4SUPPORT_DEPRECATED KSharedPtr 0067 { 0068 public: 0069 /** 0070 * Creates a null pointer. 0071 */ 0072 inline KSharedPtr() 0073 : d(nullptr) { } 0074 0075 /** 0076 * Creates a new pointer. 0077 * @param p the pointer 0078 */ 0079 inline KDELIBS4SUPPORT_DEPRECATED explicit KSharedPtr(T *p) 0080 : d(p) 0081 { 0082 if (d) { 0083 d->ref.ref(); 0084 } 0085 } 0086 0087 /** 0088 * Copies a pointer. 0089 * @param o the pointer to copy 0090 */ 0091 inline KSharedPtr(const KSharedPtr &o) 0092 : d(o.d) 0093 { 0094 if (d) { 0095 d->ref.ref(); 0096 } 0097 } 0098 0099 /** 0100 * Unreferences the object that this pointer points to. If it was 0101 * the last reference, the object will be deleted. 0102 */ 0103 inline ~KSharedPtr() 0104 { 0105 if (d && !d->ref.deref()) { 0106 delete d; 0107 } 0108 } 0109 0110 inline KSharedPtr<T> &operator= (const KSharedPtr &o) 0111 { 0112 attach(o.d); 0113 return *this; 0114 } 0115 inline bool operator== (const KSharedPtr &o) const 0116 { 0117 return (d == o.d); 0118 } 0119 inline bool operator!= (const KSharedPtr &o) const 0120 { 0121 return (d != o.d); 0122 } 0123 inline bool operator< (const KSharedPtr &o) const 0124 { 0125 return (d < o.d); 0126 } 0127 0128 inline KSharedPtr<T> &operator= (T *p) 0129 { 0130 attach(p); 0131 return *this; 0132 } 0133 inline bool operator== (const T *p) const 0134 { 0135 return (d == p); 0136 } 0137 inline bool operator!= (const T *p) const 0138 { 0139 return (d != p); 0140 } 0141 0142 /** 0143 * Test if the shared pointer is NOT null. 0144 * @return true if the shared pointer is NOT null, false otherwise. 0145 * @see isNull 0146 */ 0147 inline operator bool() const 0148 { 0149 return (d != nullptr); 0150 } 0151 0152 /** 0153 * @return the pointer 0154 */ 0155 inline T *data() 0156 { 0157 return d; 0158 } 0159 0160 /** 0161 * @return the pointer 0162 */ 0163 inline const T *data() const 0164 { 0165 return d; 0166 } 0167 0168 /** 0169 * @return a const pointer to the shared object. 0170 */ 0171 inline const T *constData() const 0172 { 0173 return d; 0174 } 0175 0176 inline const T &operator*() const 0177 { 0178 Q_ASSERT(d); 0179 return *d; 0180 } 0181 inline T &operator*() 0182 { 0183 Q_ASSERT(d); 0184 return *d; 0185 } 0186 inline const T *operator->() const 0187 { 0188 Q_ASSERT(d); 0189 return d; 0190 } 0191 inline T *operator->() 0192 { 0193 Q_ASSERT(d); 0194 return d; 0195 } 0196 0197 /** 0198 * Attach the given pointer to the current KSharedPtr. 0199 * If the previous shared pointer is not owned by any KSharedPtr, 0200 * it is deleted. 0201 */ 0202 void attach(T *p); 0203 0204 /** 0205 * Clear the pointer, i.e. make it a null pointer. 0206 */ 0207 void clear(); 0208 0209 /** 0210 * Returns the number of references. 0211 * @return the number of references 0212 */ 0213 inline int count() const 0214 { 0215 return d ? 0216 d->ref.load() 0217 : 0; 0218 } // for debugging purposes 0219 0220 /** 0221 * Test if the shared pointer is null. 0222 * @return true if the pointer is null, false otherwise. 0223 * @see opertor (bool) 0224 */ 0225 inline bool isNull() const 0226 { 0227 return (d == 0); 0228 } 0229 0230 /** 0231 * @return Whether this is the only shared pointer pointing to 0232 * to the pointee, or whether it's shared among multiple 0233 * shared pointers. 0234 */ 0235 inline bool isUnique() const 0236 { 0237 return count() == 1; 0238 } 0239 0240 template <class U> friend class KSharedPtr; 0241 0242 /** 0243 * Convert KSharedPtr<U> to KSharedPtr<T>, using a static_cast. 0244 * This will compile whenever T* and U* are compatible, i.e. 0245 * T is a subclass of U or vice-versa. 0246 * Example syntax: 0247 * <code> 0248 * KSharedPtr<T> tPtr; 0249 * KSharedPtr<U> uPtr = KSharedPtr<U>::staticCast( tPtr ); 0250 * </code> 0251 */ 0252 template <class U> 0253 static KSharedPtr<T> staticCast(const KSharedPtr<U> &o) 0254 { 0255 return KSharedPtr<T>(static_cast<T *>(o.d)); 0256 } 0257 /** 0258 * Convert KSharedPtr<U> to KSharedPtr<T>, using a dynamic_cast. 0259 * This will compile whenever T* and U* are compatible, i.e. 0260 * T is a subclass of U or vice-versa. 0261 * Example syntax: 0262 * <code> 0263 * KSharedPtr<T> tPtr; 0264 * KSharedPtr<U> uPtr = KSharedPtr<U>::dynamicCast( tPtr ); 0265 * </code> 0266 * Since a dynamic_cast is used, if U derives from T, and tPtr isn't an instance of U, uPtr will be 0. 0267 */ 0268 template <class U> 0269 static KSharedPtr<T> dynamicCast(const KSharedPtr<U> &o) 0270 { 0271 return KSharedPtr<T>(dynamic_cast<T *>(o.d)); 0272 } 0273 0274 protected: 0275 T *d; 0276 }; 0277 0278 template <class T> 0279 Q_INLINE_TEMPLATE bool operator== (const T *p, const KSharedPtr<T> &o) 0280 { 0281 return (o == p); 0282 } 0283 0284 template <class T> 0285 Q_INLINE_TEMPLATE bool operator!= (const T *p, const KSharedPtr<T> &o) 0286 { 0287 return (o != p); 0288 } 0289 0290 template <class T> 0291 Q_INLINE_TEMPLATE void KSharedPtr<T>::attach(T *p) 0292 { 0293 if (d != p) { 0294 if (p) { 0295 p->ref.ref(); 0296 } 0297 if (d && !d->ref.deref()) { 0298 delete d; 0299 } 0300 d = p; 0301 } 0302 } 0303 0304 template <class T> 0305 Q_INLINE_TEMPLATE void KSharedPtr<T>::clear() 0306 { 0307 attach(static_cast<T *>(0)); 0308 } 0309 0310 #endif 0311