Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 : ** Contact: http://www.qt-project.org/legal
5 : **
6 : ** This file is part of the QtCore module of the Qt Toolkit.
7 : **
8 : ** $QT_BEGIN_LICENSE:LGPL$
9 : ** Commercial License Usage
10 : ** Licensees holding valid commercial Qt licenses may use this file in
11 : ** accordance with the commercial license agreement provided with the
12 : ** Software or, alternatively, in accordance with the terms contained in
13 : ** a written agreement between you and Digia. For licensing terms and
14 : ** conditions see http://qt.digia.com/licensing. For further information
15 : ** use the contact form at http://qt.digia.com/contact-us.
16 : **
17 : ** GNU Lesser General Public License Usage
18 : ** Alternatively, this file may be used under the terms of the GNU Lesser
19 : ** General Public License version 2.1 as published by the Free Software
20 : ** Foundation and appearing in the file LICENSE.LGPL included in the
21 : ** packaging of this file. Please review the following information to
22 : ** ensure the GNU Lesser General Public License version 2.1 requirements
23 : ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 : **
25 : ** In addition, as a special exception, Digia gives you certain additional
26 : ** rights. These rights are described in the Digia Qt LGPL Exception
27 : ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 : **
29 : ** GNU General Public License Usage
30 : ** Alternatively, this file may be used under the terms of the GNU
31 : ** General Public License version 3.0 as published by the Free Software
32 : ** Foundation and appearing in the file LICENSE.GPL included in the
33 : ** packaging of this file. Please review the following information to
34 : ** ensure the GNU General Public License version 3.0 requirements will be
35 : ** met: http://www.gnu.org/copyleft/gpl.html.
36 : **
37 : **
38 : ** $QT_END_LICENSE$
39 : **
40 : ****************************************************************************/
41 :
42 : #include <QtCore/qglobal.h>
43 :
44 : #ifndef QATOMIC_H
45 : #define QATOMIC_H
46 :
47 : #include <QtCore/qbasicatomic.h>
48 :
49 : QT_BEGIN_NAMESPACE
50 :
51 :
52 : #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && !defined(Q_CC_INTEL)
53 : # pragma GCC diagnostic push
54 : # pragma GCC diagnostic ignored "-Wextra"
55 : #endif
56 :
57 : // High-level atomic integer operations
58 : template <typename T>
59 : class QAtomicInteger : public QBasicAtomicInteger<T>
60 : {
61 : public:
62 : // Non-atomic API
63 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
64 78 : constexpr QAtomicInteger(T value = 0) Q_DECL_NOTHROW : QBasicAtomicInteger<T>(value) {}
65 : #else
66 : inline QAtomicInteger(T value = 0) Q_DECL_NOTHROW
67 : {
68 : this->_q_value = value;
69 : }
70 : #endif
71 :
72 : inline QAtomicInteger(const QAtomicInteger &other) Q_DECL_NOTHROW
73 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
74 : : QBasicAtomicInteger<T>()
75 : #endif
76 : {
77 : this->storeRelease(other.loadAcquire());
78 : }
79 :
80 : inline QAtomicInteger &operator=(const QAtomicInteger &other) Q_DECL_NOTHROW
81 : {
82 : this->storeRelease(other.loadAcquire());
83 : return *this;
84 : }
85 :
86 : #ifdef Q_QDOC
87 : int load() const;
88 : int loadAcquire() const;
89 : void store(int newValue);
90 : void storeRelease(int newValue);
91 :
92 : operator int() const;
93 : QAtomicInteger &operator=(int);
94 :
95 : static Q_DECL_CONSTEXPR bool isReferenceCountingNative();
96 : static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree();
97 :
98 : bool ref();
99 : bool deref();
100 :
101 : static Q_DECL_CONSTEXPR bool isTestAndSetNative();
102 : static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree();
103 :
104 : bool testAndSetRelaxed(int expectedValue, int newValue);
105 : bool testAndSetAcquire(int expectedValue, int newValue);
106 : bool testAndSetRelease(int expectedValue, int newValue);
107 : bool testAndSetOrdered(int expectedValue, int newValue);
108 :
109 : static Q_DECL_CONSTEXPR bool isFetchAndStoreNative();
110 : static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree();
111 :
112 : int fetchAndStoreRelaxed(int newValue);
113 : int fetchAndStoreAcquire(int newValue);
114 : int fetchAndStoreRelease(int newValue);
115 : int fetchAndStoreOrdered(int newValue);
116 :
117 : static Q_DECL_CONSTEXPR bool isFetchAndAddNative();
118 : static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree();
119 :
120 : int fetchAndAddRelaxed(int valueToAdd);
121 : int fetchAndAddAcquire(int valueToAdd);
122 : int fetchAndAddRelease(int valueToAdd);
123 : int fetchAndAddOrdered(int valueToAdd);
124 :
125 : int fetchAndSubRelaxed(int valueToSub);
126 : int fetchAndSubAcquire(int valueToSub);
127 : int fetchAndSubRelease(int valueToSub);
128 : int fetchAndSubOrdered(int valueToSub);
129 :
130 : int fetchAndOrRelaxed(int valueToOr);
131 : int fetchAndOrAcquire(int valueToOr);
132 : int fetchAndOrRelease(int valueToOr);
133 : int fetchAndOrOrdered(int valueToOr);
134 :
135 : int fetchAndAndRelaxed(int valueToAnd);
136 : int fetchAndAndAcquire(int valueToAnd);
137 : int fetchAndAndRelease(int valueToAnd);
138 : int fetchAndAndOrdered(int valueToAnd);
139 :
140 : int fetchAndXorRelaxed(int valueToXor);
141 : int fetchAndXorAcquire(int valueToXor);
142 : int fetchAndXorRelease(int valueToXor);
143 : int fetchAndXorOrdered(int valueToXor);
144 :
145 : int operator++();
146 : int operator++(int);
147 : int operator--();
148 : int operator--(int);
149 : int operator+=(int value);
150 : int operator-=(int value);
151 : int operator|=(int value);
152 : int operator&=(int value);
153 : int operator^=(int value);
154 : #endif
155 : };
156 :
157 : class QAtomicInt : public QAtomicInteger<int>
158 : {
159 : public:
160 : // Non-atomic API
161 : // We could use QT_COMPILER_INHERITING_CONSTRUCTORS, but we need only one;
162 : // the implicit definition for all the others is fine.
163 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
164 : constexpr
165 : #endif
166 78 : QAtomicInt(int value = 0) Q_DECL_NOTHROW : QAtomicInteger<int>(value) {}
167 : };
168 :
169 : // High-level atomic pointer operations
170 : template <typename T>
171 : class QAtomicPointer : public QBasicAtomicPointer<T>
172 : {
173 : public:
174 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
175 : constexpr QAtomicPointer(T *value = 0) Q_DECL_NOTHROW : QBasicAtomicPointer<T>(value) {}
176 : #else
177 : inline QAtomicPointer(T *value = 0) Q_DECL_NOTHROW
178 : {
179 : this->store(value);
180 : }
181 : #endif
182 : inline QAtomicPointer(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
183 : {
184 : this->storeRelease(other.loadAcquire());
185 : }
186 :
187 : inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
188 : {
189 : this->storeRelease(other.loadAcquire());
190 : return *this;
191 : }
192 :
193 : #ifdef Q_QDOC
194 : T *load() const;
195 : T *loadAcquire() const;
196 : void store(T *newValue);
197 : void storeRelease(T *newValue);
198 :
199 : static Q_DECL_CONSTEXPR bool isTestAndSetNative();
200 : static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree();
201 :
202 : bool testAndSetRelaxed(T *expectedValue, T *newValue);
203 : bool testAndSetAcquire(T *expectedValue, T *newValue);
204 : bool testAndSetRelease(T *expectedValue, T *newValue);
205 : bool testAndSetOrdered(T *expectedValue, T *newValue);
206 :
207 : static Q_DECL_CONSTEXPR bool isFetchAndStoreNative();
208 : static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree();
209 :
210 : T *fetchAndStoreRelaxed(T *newValue);
211 : T *fetchAndStoreAcquire(T *newValue);
212 : T *fetchAndStoreRelease(T *newValue);
213 : T *fetchAndStoreOrdered(T *newValue);
214 :
215 : static Q_DECL_CONSTEXPR bool isFetchAndAddNative();
216 : static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree();
217 :
218 : T *fetchAndAddRelaxed(qptrdiff valueToAdd);
219 : T *fetchAndAddAcquire(qptrdiff valueToAdd);
220 : T *fetchAndAddRelease(qptrdiff valueToAdd);
221 : T *fetchAndAddOrdered(qptrdiff valueToAdd);
222 : #endif
223 : };
224 :
225 : #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && !defined(Q_CC_INTEL)
226 : # pragma GCC diagnostic pop
227 : #endif
228 :
229 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
230 : # undef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
231 : #endif
232 :
233 : /*!
234 : This is a helper for the assignment operators of implicitly
235 : shared classes. Your assignment operator should look like this:
236 :
237 : \snippet code/src.corelib.thread.qatomic.h 0
238 : */
239 : template <typename T>
240 : inline void qAtomicAssign(T *&d, T *x)
241 : {
242 : if (d == x)
243 : return;
244 : x->ref.ref();
245 : if (!d->ref.deref())
246 : delete d;
247 : d = x;
248 : }
249 :
250 : /*!
251 : This is a helper for the detach method of implicitly shared
252 : classes. Your private class needs a copy constructor which copies
253 : the members and sets the refcount to 1. After that, your detach
254 : function should look like this:
255 :
256 : \snippet code/src.corelib.thread.qatomic.h 1
257 : */
258 : template <typename T>
259 : inline void qAtomicDetach(T *&d)
260 : {
261 : if (d->ref.load() == 1)
262 : return;
263 : T *x = d;
264 : d = new T(*d);
265 : if (!x->ref.deref())
266 : delete x;
267 : }
268 :
269 : QT_END_NAMESPACE
270 : #endif // QATOMIC_H
|