1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/ |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** GNU Lesser General Public License Usage |
10 | ** This file may be used under the terms of the GNU Lesser General Public |
11 | ** License version 2.1 as published by the Free Software Foundation and |
12 | ** appearing in the file LICENSE.LGPL included in the packaging of this |
13 | ** file. Please review the following information to ensure the GNU Lesser |
14 | ** General Public License version 2.1 requirements will be met: |
15 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
16 | ** |
17 | ** In addition, as a special exception, Nokia gives you certain additional |
18 | ** rights. These rights are described in the Nokia Qt LGPL Exception |
19 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
20 | ** |
21 | ** GNU General Public License Usage |
22 | ** Alternatively, this file may be used under the terms of the GNU General |
23 | ** Public License version 3.0 as published by the Free Software Foundation |
24 | ** and appearing in the file LICENSE.GPL included in the packaging of this |
25 | ** file. Please review the following information to ensure the GNU General |
26 | ** Public License version 3.0 requirements will be met: |
27 | ** http://www.gnu.org/copyleft/gpl.html. |
28 | ** |
29 | ** Other Usage |
30 | ** Alternatively, this file may be used in accordance with the terms and |
31 | ** conditions contained in a signed written agreement between you and Nokia. |
32 | ** |
33 | ** |
34 | ** |
35 | ** |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #ifndef QREADWRITELOCK_H |
43 | #define QREADWRITELOCK_H |
44 | |
45 | #include <QtCore/qglobal.h> |
46 | #include <limits.h> // ### Qt 5: remove |
47 | |
48 | QT_BEGIN_HEADER |
49 | |
50 | QT_BEGIN_NAMESPACE |
51 | |
52 | QT_MODULE(Core) |
53 | |
54 | #ifndef QT_NO_THREAD |
55 | |
56 | struct QReadWriteLockPrivate; |
57 | |
58 | class Q_CORE_EXPORT QReadWriteLock |
59 | { |
60 | public: |
61 | enum RecursionMode { NonRecursive, Recursive }; |
62 | |
63 | QReadWriteLock(); // ### Qt 5: merge with below |
64 | QReadWriteLock(RecursionMode recursionMode); |
65 | ~QReadWriteLock(); |
66 | |
67 | void lockForRead(); |
68 | bool tryLockForRead(); |
69 | bool tryLockForRead(int timeout); |
70 | |
71 | void lockForWrite(); |
72 | bool tryLockForWrite(); |
73 | bool tryLockForWrite(int timeout); |
74 | |
75 | void unlock(); |
76 | |
77 | private: |
78 | Q_DISABLE_COPY(QReadWriteLock) |
79 | QReadWriteLockPrivate *d; |
80 | |
81 | friend class QWaitCondition; |
82 | }; |
83 | |
84 | #if defined(Q_CC_MSVC) |
85 | #pragma warning( push ) |
86 | #pragma warning( disable : 4312 ) // ignoring the warning from /Wp64 |
87 | #endif |
88 | |
89 | class Q_CORE_EXPORT QReadLocker |
90 | { |
91 | public: |
92 | inline QReadLocker(QReadWriteLock *readWriteLock); |
93 | |
94 | inline ~QReadLocker() |
95 | { unlock(); } |
96 | |
97 | inline void unlock() |
98 | { |
99 | if (q_val) { |
100 | if ((q_val & quintptr(1u)) == quintptr(1u)) { |
101 | q_val &= ~quintptr(1u); |
102 | readWriteLock()->unlock(); |
103 | } |
104 | } |
105 | } |
106 | |
107 | inline void relock() |
108 | { |
109 | if (q_val) { |
110 | if ((q_val & quintptr(1u)) == quintptr(0u)) { |
111 | readWriteLock()->lockForRead(); |
112 | q_val |= quintptr(1u); |
113 | } |
114 | } |
115 | } |
116 | |
117 | inline QReadWriteLock *readWriteLock() const |
118 | { return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); } |
119 | |
120 | private: |
121 | Q_DISABLE_COPY(QReadLocker) |
122 | quintptr q_val; |
123 | }; |
124 | |
125 | inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock) |
126 | : q_val(reinterpret_cast<quintptr>(areadWriteLock)) |
127 | { |
128 | Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), |
129 | "QReadLocker" , "QReadWriteLock pointer is misaligned" ); |
130 | relock(); |
131 | } |
132 | |
133 | class Q_CORE_EXPORT QWriteLocker |
134 | { |
135 | public: |
136 | inline QWriteLocker(QReadWriteLock *readWriteLock); |
137 | |
138 | inline ~QWriteLocker() |
139 | { unlock(); } |
140 | |
141 | inline void unlock() |
142 | { |
143 | if (q_val) { |
144 | if ((q_val & quintptr(1u)) == quintptr(1u)) { |
145 | q_val &= ~quintptr(1u); |
146 | readWriteLock()->unlock(); |
147 | } |
148 | } |
149 | } |
150 | |
151 | inline void relock() |
152 | { |
153 | if (q_val) { |
154 | if ((q_val & quintptr(1u)) == quintptr(0u)) { |
155 | readWriteLock()->lockForWrite(); |
156 | q_val |= quintptr(1u); |
157 | } |
158 | } |
159 | } |
160 | |
161 | inline QReadWriteLock *readWriteLock() const |
162 | { return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); } |
163 | |
164 | |
165 | private: |
166 | Q_DISABLE_COPY(QWriteLocker) |
167 | quintptr q_val; |
168 | }; |
169 | |
170 | inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock) |
171 | : q_val(reinterpret_cast<quintptr>(areadWriteLock)) |
172 | { |
173 | Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), |
174 | "QWriteLocker" , "QReadWriteLock pointer is misaligned" ); |
175 | relock(); |
176 | } |
177 | |
178 | #if defined(Q_CC_MSVC) |
179 | #pragma warning( pop ) |
180 | #endif |
181 | |
182 | #else // QT_NO_THREAD |
183 | |
184 | class Q_CORE_EXPORT QReadWriteLock |
185 | { |
186 | public: |
187 | enum RecursionMode { NonRecursive, Recursive }; |
188 | inline explicit QReadWriteLock(RecursionMode = NonRecursive) { } |
189 | inline ~QReadWriteLock() { } |
190 | |
191 | static inline void lockForRead() { } |
192 | static inline bool tryLockForRead() { return true; } |
193 | static inline bool tryLockForRead(int timeout) { Q_UNUSED(timeout); return true; } |
194 | |
195 | static inline void lockForWrite() { } |
196 | static inline bool tryLockForWrite() { return true; } |
197 | static inline bool tryLockForWrite(int timeout) { Q_UNUSED(timeout); return true; } |
198 | |
199 | static inline void unlock() { } |
200 | |
201 | private: |
202 | Q_DISABLE_COPY(QReadWriteLock) |
203 | }; |
204 | |
205 | class Q_CORE_EXPORT QReadLocker |
206 | { |
207 | public: |
208 | inline QReadLocker(QReadWriteLock *) { } |
209 | inline ~QReadLocker() { } |
210 | |
211 | static inline void unlock() { } |
212 | static inline void relock() { } |
213 | static inline QReadWriteLock *readWriteLock() { return 0; } |
214 | |
215 | private: |
216 | Q_DISABLE_COPY(QReadLocker) |
217 | }; |
218 | |
219 | class Q_CORE_EXPORT QWriteLocker |
220 | { |
221 | public: |
222 | inline explicit QWriteLocker(QReadWriteLock *) { } |
223 | inline ~QWriteLocker() { } |
224 | |
225 | static inline void unlock() { } |
226 | static inline void relock() { } |
227 | static inline QReadWriteLock *readWriteLock() { return 0; } |
228 | |
229 | private: |
230 | Q_DISABLE_COPY(QWriteLocker) |
231 | }; |
232 | |
233 | #endif // QT_NO_THREAD |
234 | |
235 | QT_END_NAMESPACE |
236 | |
237 | QT_END_HEADER |
238 | |
239 | #endif // QREADWRITELOCK_H |
240 | |