src/corelib/thread/qatomic.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtCore module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #ifndef QATOMIC_H
00025 #define QATOMIC_H
00026 
00027 #if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC)
00028 #  include <QtCore/qatomic_generic.h>
00029 #else
00030 #  include <QtCore/qatomic_arch.h>
00031 #endif
00032 #include <QtCore/qglobal.h>
00033 
00034 QT_BEGIN_HEADER
00035 
00036 QT_MODULE(Core)
00037 
00038 #ifndef Q_SPECIALIZED_QATOMIC
00039 
00040 /*
00041     We assume that the following 8 functions have been declared by the
00042     platform specific qatomic.h:
00043 
00044     int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
00045     int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval);
00046     int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval);
00047 
00048     int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
00049     int q_atomic_increment(volatile int *ptr);
00050     int q_atomic_decrement(volatile int *ptr);
00051     int q_atomic_set_int(volatile int *ptr, int newval);
00052     void *q_atomic_set_ptr(volatile void *ptr, void *newval);
00053 
00054     If you cannot implement these functions efficiently on your
00055     platform without great difficulty, consider defining
00056     Q_SPECIALIZED_QATOMIC.  By doing this, you need to implement:
00057 
00058     struct QBasicAtomic;
00059     template <typename T> struct QBasicAtomicPointer<T>;
00060     int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
00061     void *q_atomic_set_ptr(volatile void *ptr, void *newval);
00062 */
00063 
00064 struct QBasicAtomic {
00065     volatile int atomic;
00066 
00067     void init(int x = 0)
00068     { atomic = x; }
00069 
00070     inline bool ref()
00071     { return q_atomic_increment(&atomic) != 0; }
00072 
00073     inline bool deref()
00074     { return q_atomic_decrement(&atomic) != 0; }
00075 
00076     inline bool operator==(int x) const
00077     { return atomic == x; }
00078 
00079     inline bool operator!=(int x) const
00080     { return atomic != x; }
00081 
00082     inline bool operator!() const
00083     { return atomic == 0; }
00084 
00085     inline operator int() const
00086     { return atomic; }
00087 
00088     inline QBasicAtomic &operator=(int x)
00089     {
00090         (void) q_atomic_set_int(&atomic, x);
00091         return *this;
00092     }
00093 
00094     inline bool testAndSet(int expected, int newval)
00095     { return q_atomic_test_and_set_int(&atomic, expected, newval) != 0; }
00096 
00097     inline bool testAndSetAcquire(int expected, int newval)
00098     { return q_atomic_test_and_set_acquire_int(&atomic, expected, newval) != 0; }
00099 
00100     inline bool testAndSetRelease(int expected, int newval)
00101     { return q_atomic_test_and_set_release_int(&atomic, expected, newval) != 0; }
00102 
00103     inline int exchange(int newval)
00104     { return q_atomic_set_int(&atomic, newval); }
00105 };
00106 
00107 template <typename T>
00108 struct QBasicAtomicPointer
00109 {
00110     volatile T *pointer;
00111 
00112     void init(T *t = 0)
00113     { pointer = t; }
00114 
00115     inline bool operator==(T *t) const
00116     { return pointer == t; }
00117 
00118     inline bool operator!=(T *t) const
00119     { return !operator==(t); }
00120 
00121     inline bool operator!() const
00122     { return operator==(0); }
00123 
00124     inline operator T *() const
00125     { return const_cast<T *>(pointer); }
00126 
00127     inline T *operator->() const
00128     { return const_cast<T *>(pointer); }
00129 
00130     inline QBasicAtomicPointer<T> &operator=(T *t)
00131     {
00132         (void) q_atomic_set_ptr(&pointer, t);
00133         return *this;
00134     }
00135 
00136     inline bool testAndSet(T *expected, T *newval)
00137     { return q_atomic_test_and_set_ptr(&pointer, expected, newval); }
00138 
00139     inline T *exchange(T * newval)
00140     { return static_cast<T *>(q_atomic_set_ptr(&pointer, newval)); }
00141 };
00142 
00143 #define Q_ATOMIC_INIT(a) { (a) }
00144 
00145 #endif // Q_SPECIALIZED_QATOMIC
00146 
00147 template <typename T>
00148 inline T qAtomicSetPtr(volatile T *ptr, T newval)
00149 { return static_cast<T>(q_atomic_set_ptr(ptr, newval)); }
00150 
00151 // High-level atomic integer operations
00152 class QAtomic : public QBasicAtomic
00153 {
00154 public:
00155     inline QAtomic(int x = 0)
00156     { init(x); }
00157     inline QAtomic(const QAtomic &copy)
00158     { init(copy); }
00159 
00160     inline QAtomic &operator=(int x)
00161     {
00162         (void) QBasicAtomic::operator=(x);
00163         return *this;
00164     }
00165 
00166     inline QAtomic &operator=(const QAtomic &copy)
00167     {
00168         (void) QBasicAtomic::operator=(copy);
00169         return *this;
00170     }
00171 };
00172 
00173 // High-level atomic pointer operations
00174 template <typename T>
00175 class QAtomicPointer : public QBasicAtomicPointer<T>
00176 {
00177 public:
00178     inline QAtomicPointer(T *t = 0)
00179     { init(t); }
00180     inline QAtomicPointer(const QAtomicPointer<T> &copy)
00181     { init(copy); }
00182 
00183     inline QAtomicPointer<T> &operator=(T *t)
00184     {
00185         (void) QBasicAtomicPointer<T>::operator=(t);
00186         return *this;
00187     }
00188 
00189     inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &copy)
00190     {
00191         (void) QBasicAtomicPointer<T>::operator=(copy);
00192         return *this;
00193     }
00194 };
00195 
00205 template <typename T>
00206 inline void qAtomicAssign(T *&d, T *x)
00207 {
00208     x->ref.ref();
00209     x = qAtomicSetPtr(&d, x);
00210     if (!x->ref.deref())
00211         delete x;
00212 }
00213 
00217 template <typename T>
00218 inline void qAtomicAssign(QBasicAtomicPointer<T> &d, T *x)
00219 {
00220     x->ref.ref();
00221     x = d.exchange(x);
00222     if (!x->ref.deref())
00223         delete x;
00224 }
00225 
00229 template <typename T>
00230 inline void qAtomicAssign(QBasicAtomicPointer<T> &d, const QBasicAtomicPointer<T> &x)
00231 { qAtomicAssign<T>(d, x); }
00232 
00243 template <typename T>
00244 inline void qAtomicDetach(T *&d)
00245 {
00246     if (d->ref == 1)
00247         return;
00248     T *x = new T(*d);
00249     x = qAtomicSetPtr(&d, x);
00250     if (!x->ref.deref())
00251         delete x;
00252 }
00253 
00257 template <typename T>
00258 inline void qAtomicDetach(QBasicAtomicPointer<T> &d)
00259 {
00260     if (d->ref == 1)
00261         return;
00262     T *x = new T(*d);
00263     x = d.exchange(x);
00264     if (!x->ref.deref())
00265         delete x;
00266 }
00267 
00268 QT_END_HEADER
00269 
00270 #endif // QATOMIC_H

Generated on Thu Mar 15 11:53:36 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1