kernel/qsystemsemaphore.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
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 "qsystemsemaphore.h" -
43#include "qsystemsemaphore_p.h" -
44#include <qglobal.h> -
45 -
46QT_BEGIN_NAMESPACE -
47 -
48#ifndef QT_NO_SYSTEMSEMAPHORE -
49 -
50/*! -
51 \class QSystemSemaphore -
52 \inmodule QtCore -
53 \since 4.4 -
54 -
55 \brief The QSystemSemaphore class provides a general counting system semaphore. -
56 -
57 A semaphore is a generalization of a mutex. While a mutex can be -
58 locked only once, a semaphore can be acquired multiple times. -
59 Typically, a semaphore is used to protect a certain number of -
60 identical resources. -
61 -
62 Like its lighter counterpart QSemaphore, a QSystemSemaphore can be -
63 accessed from multiple \l {QThread} {threads}. Unlike QSemaphore, a -
64 QSystemSemaphore can also be accessed from multiple \l {QProcess} -
65 {processes}. This means QSystemSemaphore is a much heavier class, so -
66 if your application doesn't need to access your semaphores across -
67 multiple processes, you will probably want to use QSemaphore. -
68 -
69 Semaphores support two fundamental operations, acquire() and release(): -
70 -
71 acquire() tries to acquire one resource. If there isn't a resource -
72 available, the call blocks until a resource becomes available. Then -
73 the resource is acquired and the call returns. -
74 -
75 release() releases one resource so it can be acquired by another -
76 process. The function can also be called with a parameter n > 1, -
77 which releases n resources. -
78 -
79 A system semaphore is created with a string key that other processes -
80 can use to use the same semaphore. -
81 -
82 Example: Create a system semaphore -
83 \snippet code/src_corelib_kernel_qsystemsemaphore.cpp 0 -
84 -
85 A typical application of system semaphores is for controlling access -
86 to a circular buffer shared by a producer process and a consumer -
87 processes. -
88 -
89 \section1 Platform-Specific Behavior -
90 -
91 When using this class, be aware of the following platform -
92 differences: -
93 -
94 \b{Windows:} QSystemSemaphore does not own its underlying system -
95 semaphore. Windows owns it. This means that when all instances of -
96 QSystemSemaphore for a particular key have been destroyed, either by -
97 having their destructors called, or because one or more processes -
98 crash, Windows removes the underlying system semaphore. -
99 -
100 \b{Unix:} -
101 -
102 \list -
103 \li QSystemSemaphore owns the underlying system semaphore -
104 in Unix systems. This means that the last process having an instance of -
105 QSystemSemaphore for a particular key must remove the underlying -
106 system semaphore in its destructor. If the last process crashes -
107 without running the QSystemSemaphore destructor, Unix does not -
108 automatically remove the underlying system semaphore, and the -
109 semaphore survives the crash. A subsequent process that constructs a -
110 QSystemSemaphore with the same key will then be given the existing -
111 system semaphore. In that case, if the QSystemSemaphore constructor -
112 has specified its \l {QSystemSemaphore::AccessMode} {access mode} as -
113 \l {QSystemSemaphore::} {Open}, its initial resource count will not -
114 be reset to the one provided but remain set to the value it received -
115 in the crashed process. To protect against this, the first process -
116 to create a semaphore for a particular key (usually a server), must -
117 pass its \l {QSystemSemaphore::AccessMode} {access mode} as \l -
118 {QSystemSemaphore::} {Create}, which will force Unix to reset the -
119 resource count in the underlying system semaphore. -
120 -
121 \li When a process using QSystemSemaphore terminates for -
122 any reason, Unix automatically reverses the effect of all acquire -
123 operations that were not released. Thus if the process acquires a -
124 resource and then exits without releasing it, Unix will release that -
125 resource. -
126 -
127 \endlist -
128 -
129 \sa QSharedMemory, QSemaphore -
130 */ -
131 -
132/*! -
133 Requests a system semaphore for the specified \a key. The parameters -
134 \a initialValue and \a mode are used according to the following -
135 rules, which are system dependent. -
136 -
137 In Unix, if the \a mode is \l {QSystemSemaphore::} {Open} and the -
138 system already has a semaphore identified by \a key, that semaphore -
139 is used, and the semaphore's resource count is not changed, i.e., \a -
140 initialValue is ignored. But if the system does not already have a -
141 semaphore identified by \a key, it creates a new semaphore for that -
142 key and sets its resource count to \a initialValue. -
143 -
144 In Unix, if the \a mode is \l {QSystemSemaphore::} {Create} and the -
145 system already has a semaphore identified by \a key, that semaphore -
146 is used, and its resource count is set to \a initialValue. If the -
147 system does not already have a semaphore identified by \a key, it -
148 creates a new semaphore for that key and sets its resource count to -
149 \a initialValue. -
150 -
151 In Windows, \a mode is ignored, and the system always tries to -
152 create a semaphore for the specified \a key. If the system does not -
153 already have a semaphore identified as \a key, it creates the -
154 semaphore and sets its resource count to \a initialValue. But if the -
155 system already has a semaphore identified as \a key it uses that -
156 semaphore and ignores \a initialValue. -
157 -
158 The \l {QSystemSemaphore::AccessMode} {mode} parameter is only used -
159 in Unix systems to handle the case where a semaphore survives a -
160 process crash. In that case, the next process to allocate a -
161 semaphore with the same \a key will get the semaphore that survived -
162 the crash, and unless \a mode is \l {QSystemSemaphore::} {Create}, -
163 the resource count will not be reset to \a initialValue but will -
164 retain the initial value it had been given by the crashed process. -
165 -
166 \sa acquire(), key() -
167 */ -
168QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode) -
169 : d(new QSystemSemaphorePrivate) -
170{ -
171 setKey(key, initialValue, mode);
executed (the execution status of this line is deduced): setKey(key, initialValue, mode);
-
172}
executed: }
Execution Count:47
47
173 -
174/*! -
175 The destructor destroys the QSystemSemaphore object, but the -
176 underlying system semaphore is not removed from the system unless -
177 this instance of QSystemSemaphore is the last one existing for that -
178 system semaphore. -
179 -
180 Two important side effects of the destructor depend on the system. -
181 In Windows, if acquire() has been called for this semaphore but not -
182 release(), release() will not be called by the destructor, nor will -
183 the resource be released when the process exits normally. This would -
184 be a program bug which could be the cause of a deadlock in another -
185 process trying to acquire the same resource. In Unix, acquired -
186 resources that are not released before the destructor is called are -
187 automatically released when the process exits. -
188*/ -
189QSystemSemaphore::~QSystemSemaphore() -
190{ -
191 d->cleanHandle();
executed (the execution status of this line is deduced): d->cleanHandle();
-
192}
executed: }
Execution Count:47
47
193 -
194/*! -
195 \enum QSystemSemaphore::AccessMode -
196 -
197 This enum is used by the constructor and setKey(). Its purpose is to -
198 enable handling the problem in Unix implementations of semaphores -
199 that survive a crash. In Unix, when a semaphore survives a crash, we -
200 need a way to force it to reset its resource count, when the system -
201 reuses the semaphore. In Windows, where semaphores can't survive a -
202 crash, this enum has no effect. -
203 -
204 \value Open If the semaphore already exists, its initial resource -
205 count is not reset. If the semaphore does not already exist, it is -
206 created and its initial resource count set. -
207 -
208 \value Create QSystemSemaphore takes ownership of the semaphore and -
209 sets its resource count to the requested value, regardless of -
210 whether the semaphore already exists by having survived a crash. -
211 This value should be passed to the constructor, when the first -
212 semaphore for a particular key is constructed and you know that if -
213 the semaphore already exists it could only be because of a crash. In -
214 Windows, where a semaphore can't survive a crash, Create and Open -
215 have the same behavior. -
216*/ -
217 -
218/*! -
219 This function works the same as the constructor. It reconstructs -
220 this QSystemSemaphore object. If the new \a key is different from -
221 the old key, calling this function is like calling the destructor of -
222 the semaphore with the old key, then calling the constructor to -
223 create a new semaphore with the new \a key. The \a initialValue and -
224 \a mode parameters are as defined for the constructor. -
225 -
226 \sa QSystemSemaphore(), key() -
227 */ -
228void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode mode) -
229{ -
230 if (key == d->key && mode == Open)
evaluated: key == d->key
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:46
partially evaluated: mode == Open
TRUEFALSE
yes
Evaluation Count:4
no
Evaluation Count:0
0-46
231 return;
executed: return;
Execution Count:4
4
232 d->error = NoError;
executed (the execution status of this line is deduced): d->error = NoError;
-
233 d->errorString = QString();
executed (the execution status of this line is deduced): d->errorString = QString();
-
234#if !defined(Q_OS_WIN) -
235 // optimization to not destroy/create the file & semaphore -
236 if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) {
partially evaluated: key == d->key
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:46
never evaluated: mode == Create
never evaluated: d->createdSemaphore
never evaluated: d->createdFile
0-46
237 d->initialValue = initialValue;
never executed (the execution status of this line is deduced): d->initialValue = initialValue;
-
238 d->unix_key = -1;
never executed (the execution status of this line is deduced): d->unix_key = -1;
-
239 d->handle(mode);
never executed (the execution status of this line is deduced): d->handle(mode);
-
240 return;
never executed: return;
0
241 } -
242#endif -
243 d->cleanHandle();
executed (the execution status of this line is deduced): d->cleanHandle();
-
244 d->key = key;
executed (the execution status of this line is deduced): d->key = key;
-
245 d->initialValue = initialValue;
executed (the execution status of this line is deduced): d->initialValue = initialValue;
-
246 // cache the file name so it doesn't have to be generated all the time. -
247 d->fileName = d->makeKeyFileName();
executed (the execution status of this line is deduced): d->fileName = d->makeKeyFileName();
-
248 d->handle(mode);
executed (the execution status of this line is deduced): d->handle(mode);
-
249}
executed: }
Execution Count:46
46
250 -
251/*! -
252 Returns the key assigned to this system semaphore. The key is the -
253 name by which the semaphore can be accessed from other processes. -
254 -
255 \sa setKey() -
256 */ -
257QString QSystemSemaphore::key() const -
258{ -
259 return d->key;
executed: return d->key;
Execution Count:6
6
260} -
261 -
262/*! -
263 Acquires one of the resources guarded by this semaphore, if there is -
264 one available, and returns true. If all the resources guarded by this -
265 semaphore have already been acquired, the call blocks until one of -
266 them is released by another process or thread having a semaphore -
267 with the same key. -
268 -
269 If false is returned, a system error has occurred. Call error() -
270 to get a value of QSystemSemaphore::SystemSemaphoreError that -
271 indicates which error occurred. -
272 -
273 \sa release() -
274 */ -
275bool QSystemSemaphore::acquire() -
276{ -
277 return d->modifySemaphore(-1);
executed: return d->modifySemaphore(-1);
Execution Count:5
5
278} -
279 -
280/*! -
281 Releases \a n resources guarded by the semaphore. Returns true -
282 unless there is a system error. -
283 -
284 Example: Create a system semaphore having five resources; acquire -
285 them all and then release them all. -
286 -
287 \snippet code/src_corelib_kernel_qsystemsemaphore.cpp 1 -
288 -
289 This function can also "create" resources. For example, immediately -
290 following the sequence of statements above, suppose we add the -
291 statement: -
292 -
293 \snippet code/src_corelib_kernel_qsystemsemaphore.cpp 2 -
294 -
295 Ten new resources are now guarded by the semaphore, in addition to -
296 the five that already existed. You would not normally use this -
297 function to create more resources. -
298 -
299 \sa acquire() -
300 */ -
301bool QSystemSemaphore::release(int n) -
302{ -
303 if (n == 0)
partially evaluated: n == 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5
0-5
304 return true;
never executed: return true;
0
305 if (n < 0) {
partially evaluated: n < 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:5
0-5
306 qWarning("QSystemSemaphore::release: n is negative.");
never executed (the execution status of this line is deduced): QMessageLogger("kernel/qsystemsemaphore.cpp", 306, __PRETTY_FUNCTION__).warning("QSystemSemaphore::release: n is negative.");
-
307 return false;
never executed: return false;
0
308 } -
309 return d->modifySemaphore(n);
executed: return d->modifySemaphore(n);
Execution Count:5
5
310} -
311 -
312/*! -
313 Returns a value indicating whether an error occurred, and, if so, -
314 which error it was. -
315 -
316 \sa errorString() -
317 */ -
318QSystemSemaphore::SystemSemaphoreError QSystemSemaphore::error() const -
319{ -
320 return d->error;
executed: return d->error;
Execution Count:9
9
321} -
322 -
323/*! -
324 \enum QSystemSemaphore::SystemSemaphoreError -
325 -
326 \value NoError No error occurred. -
327 -
328 \value PermissionDenied The operation failed because the caller -
329 didn't have the required permissions. -
330 -
331 \value KeyError The operation failed because of an invalid key. -
332 -
333 \value AlreadyExists The operation failed because a system -
334 semaphore with the specified key already existed. -
335 -
336 \value NotFound The operation failed because a system semaphore -
337 with the specified key could not be found. -
338 -
339 \value OutOfResources The operation failed because there was -
340 not enough memory available to fill the request. -
341 -
342 \value UnknownError Something else happened and it was bad. -
343*/ -
344 -
345/*! -
346 Returns a text description of the last error that occurred. If -
347 error() returns an \l {QSystemSemaphore::SystemSemaphoreError} {error -
348 value}, call this function to get a text string that describes the -
349 error. -
350 -
351 \sa error() -
352 */ -
353QString QSystemSemaphore::errorString() const -
354{ -
355 return d->errorString;
executed: return d->errorString;
Execution Count:8
8
356} -
357 -
358#endif // QT_NO_SYSTEMSEMAPHORE -
359 -
360QT_END_NAMESPACE -
361 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial