qshareddata.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtCore module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef QSHAREDDATA_H
00043 #define QSHAREDDATA_H
00044 
00045 #include <QtCore/qglobal.h>
00046 #include <QtCore/qatomic.h>
00047 
00048 QT_BEGIN_HEADER
00049 
00050 QT_BEGIN_NAMESPACE
00051 
00052 QT_MODULE(Core)
00053 
00054 template <class T> class QSharedDataPointer;
00055 
00056 class Q_CORE_EXPORT QSharedData
00057 {
00058 public:
00059     mutable QAtomicInt ref;
00060 
00061     inline QSharedData() : ref(0) { }
00062     inline QSharedData(const QSharedData &) : ref(0) { }
00063 
00064 private:
00065     // using the assignment operator would lead to corruption in the ref-counting
00066     QSharedData &operator=(const QSharedData &);
00067 };
00068 
00069 template <class T> class QSharedDataPointer
00070 {
00071 public:
00072     typedef T Type;
00073     typedef T *pointer;
00074 
00075     inline void detach() { if (d && d->ref != 1) detach_helper(); }
00076     inline T &operator*() { detach(); return *d; }
00077     inline const T &operator*() const { return *d; }
00078     inline T *operator->() { detach(); return d; }
00079     inline const T *operator->() const { return d; }
00080     inline operator T *() { detach(); return d; }
00081     inline operator const T *() const { return d; }
00082     inline T *data() { detach(); return d; }
00083     inline const T *data() const { return d; }
00084     inline const T *constData() const { return d; }
00085 
00086     inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; }
00087     inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; }
00088 
00089     inline QSharedDataPointer() { d = 0; }
00090     inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
00091 
00092     explicit QSharedDataPointer(T *data);
00093     inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
00094     inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) {
00095         if (o.d != d) {
00096             if (o.d)
00097                 o.d->ref.ref();
00098             T *old = d;
00099             d = o.d;
00100             if (old && !old->ref.deref())
00101                 delete old;
00102         }
00103         return *this;
00104     }
00105     inline QSharedDataPointer &operator=(T *o) {
00106         if (o != d) {
00107             if (o)
00108                 o->ref.ref();
00109             T *old = d;
00110             d = o;
00111             if (old && !old->ref.deref())
00112                 delete old;
00113         }
00114         return *this;
00115     }
00116 
00117     inline bool operator!() const { return !d; }
00118 
00119     inline void swap(QSharedDataPointer &other)
00120     { qSwap(d, other.d); }
00121 
00122 protected:
00123     T *clone();
00124 
00125 private:
00126     void detach_helper();
00127 
00128     T *d;
00129 };
00130 
00131 template <class T> class QExplicitlySharedDataPointer
00132 {
00133 public:
00134     typedef T Type;
00135     typedef T *pointer;
00136 
00137     inline T &operator*() const { return *d; }
00138     inline T *operator->() { return d; }
00139     inline T *operator->() const { return d; }
00140     inline T *data() const { return d; }
00141     inline const T *constData() const { return d; }
00142 
00143     inline void detach() { if (d && d->ref != 1) detach_helper(); }
00144 
00145     inline void reset()
00146     {
00147         if(d && !d->ref.deref())
00148             delete d;
00149 
00150         d = 0;
00151     }
00152 
00153     inline operator bool () const { return d != 0; }
00154 
00155     inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; }
00156     inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; }
00157     inline bool operator==(const T *ptr) const { return d == ptr; }
00158     inline bool operator!=(const T *ptr) const { return d != ptr; }
00159 
00160     inline QExplicitlySharedDataPointer() { d = 0; }
00161     inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
00162 
00163     explicit QExplicitlySharedDataPointer(T *data);
00164     inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
00165 
00166 #ifndef QT_NO_MEMBER_TEMPLATES
00167     template<class X>
00168     inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data()))
00169     {
00170         if(d)
00171             d->ref.ref();
00172     }
00173 #endif
00174 
00175     inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) {
00176         if (o.d != d) {
00177             if (o.d)
00178                 o.d->ref.ref();
00179             T *old = d;
00180             d = o.d;
00181             if (old && !old->ref.deref())
00182                 delete old;
00183         }
00184         return *this;
00185     }
00186     inline QExplicitlySharedDataPointer &operator=(T *o) {
00187         if (o != d) {
00188             if (o)
00189                 o->ref.ref();
00190             T *old = d;
00191             d = o;
00192             if (old && !old->ref.deref())
00193                 delete old;
00194         }
00195         return *this;
00196     }
00197 
00198     inline bool operator!() const { return !d; }
00199 
00200     inline void swap(QExplicitlySharedDataPointer &other)
00201     { qSwap(d, other.d); }
00202 
00203 protected:
00204     T *clone();
00205 
00206 private:
00207     void detach_helper();
00208 
00209     T *d;
00210 };
00211 
00212 template <class T>
00213 Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) : d(adata)
00214 { if (d) d->ref.ref(); }
00215 
00216 template <class T>
00217 Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
00218 {
00219     return new T(*d);
00220 }
00221 
00222 template <class T>
00223 Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
00224 {
00225     T *x = clone();
00226     x->ref.ref();
00227     if (!d->ref.deref())
00228         delete d;
00229     d = x;
00230 }
00231 
00232 template <class T>
00233 Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
00234 {
00235     return new T(*d);
00236 }
00237 
00238 template <class T>
00239 Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
00240 {
00241     T *x = clone();
00242     x->ref.ref();
00243     if (!d->ref.deref())
00244         delete d;
00245     d = x;
00246 }
00247 
00248 template <class T>
00249 Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) : d(adata)
00250 { if (d) d->ref.ref(); }
00251 
00252 template <class T>
00253 Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
00254 { p1.swap(p2); }
00255 
00256 template <class T>
00257 Q_INLINE_TEMPLATE void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
00258 { p1.swap(p2); }
00259 
00260 QT_END_NAMESPACE
00261 
00262 QT_END_HEADER
00263 
00264 #endif // QSHAREDDATA_H