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