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