- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

# qatomic_sh.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 QATOMIC_SH_H
    00043 #define QATOMIC_SH_H
    00044
    00045 QT_BEGIN_HEADER
    00046
    00047 QT_BEGIN_NAMESPACE
    00048
    00049 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE
    00050
    00051 inline bool QBasicAtomicInt::isReferenceCountingNative()
    00052 { return false; }
    00053 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
    00054 { return false; }
    00055
    00056 #define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE
    00057
    00058 inline bool QBasicAtomicInt::isTestAndSetNative()
    00059 { return false; }
    00060 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
    00061 { return false; }
    00062
    00063 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE
    00064
    00065 inline bool QBasicAtomicInt::isFetchAndStoreNative()
    00066 { return false; }
    00067 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
    00068 { return false; }
    00069
    00070 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE
    00071
    00072 inline bool QBasicAtomicInt::isFetchAndAddNative()
    00073 { return false; }
    00074 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
    00075 { return false; }
    00076
    00077 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE
    00078
    00079 template <typename T>
    00080 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
    00081 { return false; }
    00082 template <typename T>
    00083 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
    00084 { return false; }
    00085
    00086 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE
    00087
    00088 template <typename T>
    00089 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
    00090 { return false; }
    00091 template <typename T>
    00092 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
    00093 { return false; }
    00094
    00095 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE
    00096
    00097 template <typename T>
    00098 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
    00099 { return false; }
    00100 template <typename T>
    00101 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
    00102 { return false; }
    00103
    00104 extern Q_CORE_EXPORT volatile char qt_atomic_lock;
    00105 Q_CORE_EXPORT void qt_atomic_yield(int *count);
    00106
    00107 inline int qt_atomic_tasb(volatile char *ptr)
    00108 {
    00109     register int ret;
    00110     asm volatile("tas.b @%2\n"
    00111                  "movt  %0"
    00112                  : "=&r"(ret), "=m"(*ptr)
    00113                  : "r"(ptr)
    00114                  : "cc", "memory");
    00115     return ret;
    00116 }
    00117
    00118 // Reference counting
    00119
    00120 inline bool QBasicAtomicInt::ref()
    00121 {
    00122     int count = 0;
    00123     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00124         qt_atomic_yield(&count);
    00125     int originalValue = _q_value++;
    00126     qt_atomic_lock = 0;
    00127     return originalValue != -1;
    00128 }
    00129
    00130 inline bool QBasicAtomicInt::deref()
    00131 {
    00132     int count = 0;
    00133     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00134         qt_atomic_yield(&count);
    00135     int originalValue = _q_value--;
    00136     qt_atomic_lock = 0;
    00137     return originalValue != 1;
    00138 }
    00139
    00140 // Test and set for integers
    00141
    00142 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
    00143 {
    00144     bool returnValue = false;
    00145     int count = 0;
    00146     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00147         qt_atomic_yield(&count);
    00148     if (_q_value == expectedValue) {
    00149         _q_value = newValue;
    00150         returnValue = true;
    00151     }
    00152     qt_atomic_lock = 0;
    00153     return returnValue;
    00154 }
    00155
    00156 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
    00157 {
    00158     return testAndSetOrdered(expectedValue, newValue);
    00159 }
    00160
    00161 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
    00162 {
    00163     return testAndSetOrdered(expectedValue, newValue);
    00164 }
    00165
    00166 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
    00167 {
    00168     return testAndSetOrdered(expectedValue, newValue);
    00169 }
    00170
    00171 // Fetch and store for integers
    00172
    00173 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
    00174 {
    00175     int count = 0;
    00176     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00177         qt_atomic_yield(&count);
    00178     int originalValue = _q_value;
    00179     _q_value = newValue;
    00180     qt_atomic_lock = 0;
    00181     return originalValue;
    00182 }
    00183
    00184 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
    00185 {
    00186     return fetchAndStoreOrdered(newValue);
    00187 }
    00188
    00189 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
    00190 {
    00191     return fetchAndStoreOrdered(newValue);
    00192 }
    00193
    00194 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
    00195 {
    00196     return fetchAndStoreOrdered(newValue);
    00197 }
    00198
    00199 // Fetch and add for integers
    00200
    00201 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
    00202 {
    00203     int count = 0;
    00204     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00205         qt_atomic_yield(&count);
    00206     int originalValue = _q_value;
    00207     _q_value += valueToAdd;
    00208     qt_atomic_lock = 0;
    00209     return originalValue;
    00210 }
    00211
    00212 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
    00213 {
    00214     return fetchAndAddOrdered(valueToAdd);
    00215 }
    00216
    00217 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
    00218 {
    00219     return fetchAndAddOrdered(valueToAdd);
    00220 }
    00221
    00222 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
    00223 {
    00224     return fetchAndAddOrdered(valueToAdd);
    00225 }
    00226
    00227 // Test and set for pointers
    00228
    00229 template <typename T>
    00230 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
    00231 {
    00232     bool returnValue = false;
    00233     int count = 0;
    00234     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00235         qt_atomic_yield(&count);
    00236     if (_q_value == expectedValue) {
    00237         _q_value = newValue;
    00238         returnValue = true;
    00239     }
    00240     qt_atomic_lock = 0;
    00241     return returnValue;
    00242 }
    00243
    00244 template <typename T>
    00245 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
    00246 {
    00247     return testAndSetOrdered(expectedValue, newValue);
    00248 }
    00249
    00250 template <typename T>
    00251 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
    00252 {
    00253     return testAndSetOrdered(expectedValue, newValue);
    00254 }
    00255
    00256 template <typename T>
    00257 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
    00258 {
    00259     return testAndSetOrdered(expectedValue, newValue);
    00260 }
    00261
    00262 // Fetch and store for pointers
    00263
    00264 template <typename T>
    00265 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
    00266 {
    00267     int count = 0;
    00268     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00269         qt_atomic_yield(&count);
    00270     T *originalValue = _q_value;
    00271     _q_value = newValue;
    00272     qt_atomic_lock = 0;
    00273     return originalValue;
    00274 }
    00275
    00276 template <typename T>
    00277 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
    00278 {
    00279     return fetchAndStoreOrdered(newValue);
    00280 }
    00281
    00282 template <typename T>
    00283 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
    00284 {
    00285     return fetchAndStoreOrdered(newValue);
    00286 }
    00287
    00288 template <typename T>
    00289 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
    00290 {
    00291     return fetchAndStoreOrdered(newValue);
    00292 }
    00293
    00294 // Fetch and add for pointers
    00295
    00296 template <typename T>
    00297 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
    00298 {
    00299     int count = 0;
    00300     while (qt_atomic_tasb(&qt_atomic_lock) == 0)
    00301         qt_atomic_yield(&count);
    00302     T *originalValue = (_q_value);
    00303     _q_value += valueToAdd;
    00304     qt_atomic_lock = 0;
    00305     return originalValue;
    00306 }
    00307
    00308 template <typename T>
    00309 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
    00310 {
    00311     return fetchAndAddOrdered(valueToAdd);
    00312 }
    00313
    00314 template <typename T>
    00315 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
    00316 {
    00317     return fetchAndAddOrdered(valueToAdd);
    00318 }
    00319
    00320 template <typename T>
    00321 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
    00322 {
    00323     return fetchAndAddOrdered(valueToAdd);
    00324 }
    00325
    00326 QT_END_NAMESPACE
    00327
    00328 QT_END_HEADER
    00329
    00330 #endif // QATOMIC_SH_H