File indexing completed on 2024-04-21 14:55:39

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