1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtCore module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtCore/qglobal.h>
47 #include <QtCore/qbasicatomic.h>
55 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
56 # pragma GCC diagnostic push
57 # pragma GCC diagnostic ignored "-Wextra"
60 // High-level atomic integer operations
61 class Q_CORE_EXPORT QAtomicInt : public QBasicAtomicInt
65 inline QAtomicInt(int value = 0)
68 this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
73 inline QAtomicInt(const QAtomicInt &other)
76 this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
81 inline QAtomicInt &operator=(int value)
87 inline QAtomicInt &operator=(const QAtomicInt &other)
89 this->store(other.load());
93 inline bool operator==(int value) const
95 return this->load() == value;
98 inline bool operator!=(int value) const
100 return this->load() != value;
103 inline operator int() const
108 inline bool operator!() const
110 return !this->load();
114 static bool isReferenceCountingNative();
115 static bool isReferenceCountingWaitFree();
120 static bool isTestAndSetNative();
121 static bool isTestAndSetWaitFree();
123 bool testAndSetRelaxed(int expectedValue, int newValue);
124 bool testAndSetAcquire(int expectedValue, int newValue);
125 bool testAndSetRelease(int expectedValue, int newValue);
126 bool testAndSetOrdered(int expectedValue, int newValue);
128 static bool isFetchAndStoreNative();
129 static bool isFetchAndStoreWaitFree();
131 int fetchAndStoreRelaxed(int newValue);
132 int fetchAndStoreAcquire(int newValue);
133 int fetchAndStoreRelease(int newValue);
134 int fetchAndStoreOrdered(int newValue);
136 static bool isFetchAndAddNative();
137 static bool isFetchAndAddWaitFree();
139 int fetchAndAddRelaxed(int valueToAdd);
140 int fetchAndAddAcquire(int valueToAdd);
141 int fetchAndAddRelease(int valueToAdd);
142 int fetchAndAddOrdered(int valueToAdd);
146 // High-level atomic pointer operations
147 template <typename T>
148 class QAtomicPointer : public QBasicAtomicPointer<T>
151 inline QAtomicPointer(T *value = 0)
153 #ifdef QT_ARCH_PARISC
154 this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
158 inline QAtomicPointer(const QAtomicPointer<T> &other)
160 #ifdef QT_ARCH_PARISC
161 this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
163 this->store(other.load());
166 inline QAtomicPointer<T> &operator=(T *value)
172 inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other)
174 this->store(other.load());
178 inline bool operator==(T *value) const
180 return this->load() == value;
183 inline bool operator!=(T *value) const
185 return this->load() != value;
188 inline bool operator!() const
190 return !this->load();
193 inline operator T *() const
198 inline T *operator->() const
204 static bool isTestAndSetNative();
205 static bool isTestAndSetWaitFree();
207 bool testAndSetRelaxed(T *expectedValue, T *newValue);
208 bool testAndSetAcquire(T *expectedValue, T *newValue);
209 bool testAndSetRelease(T *expectedValue, T *newValue);
210 bool testAndSetOrdered(T *expectedValue, T *newValue);
212 static bool isFetchAndStoreNative();
213 static bool isFetchAndStoreWaitFree();
215 T *fetchAndStoreRelaxed(T *newValue);
216 T *fetchAndStoreAcquire(T *newValue);
217 T *fetchAndStoreRelease(T *newValue);
218 T *fetchAndStoreOrdered(T *newValue);
220 static bool isFetchAndAddNative();
221 static bool isFetchAndAddWaitFree();
223 T *fetchAndAddRelaxed(qptrdiff valueToAdd);
224 T *fetchAndAddAcquire(qptrdiff valueToAdd);
225 T *fetchAndAddRelease(qptrdiff valueToAdd);
226 T *fetchAndAddOrdered(qptrdiff valueToAdd);
230 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
231 # pragma GCC diagnostic pop
235 This is a helper for the assignment operators of implicitly
236 shared classes. Your assignment operator should look like this:
238 \snippet doc/src/snippets/code/src.corelib.thread.qatomic.h 0
240 template <typename T>
241 inline void qAtomicAssign(T *&d, T *x)
252 This is a helper for the detach method of implicitly shared
253 classes. Your private class needs a copy constructor which copies
254 the members and sets the refcount to 1. After that, your detach
255 function should look like this:
257 \snippet doc/src/snippets/code/src.corelib.thread.qatomic.h 1
259 template <typename T>
260 inline void qAtomicDetach(T *&d)
262 if (d->ref.load() == 1)