qsystemsemaphore.cpp

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

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9