| 8f427b2 by axis at 2009-04-24 |
1 |
/**************************************************************************** |
|
2 |
** |
| 89c08c0 by Jason McDonald at 2012-01-11 |
3 |
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). |
| 04e3b30 by Jason McDonald at 2009-09-09 |
4 |
** All rights reserved. |
| 858c70f by Jason McDonald at 2009-06-16 |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
| 8f427b2 by axis at 2009-04-24 |
6 |
** |
|
7 |
** This file is part of the QtCore module of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** GNU Lesser General Public License Usage |
| 1eea52e by Jyri Tahtela at 2011-05-13 |
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. |
| 8f427b2 by axis at 2009-04-24 |
17 |
** |
| 04e3b30 by Jason McDonald at 2009-09-09 |
18 |
** In addition, as a special exception, Nokia gives you certain additional |
| 1eea52e by Jyri Tahtela at 2011-05-13 |
19 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
| 04e3b30 by Jason McDonald at 2009-09-09 |
20 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 8f427b2 by axis at 2009-04-24 |
21 |
** |
| 1eea52e by Jyri Tahtela at 2011-05-13 |
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. |
|
29 |
** |
|
30 |
** Other Usage |
|
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. |
| 309db73 by Jason McDonald at 2009-08-31 |
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
| 8f427b2 by axis at 2009-04-24 |
37 |
** |
|
38 |
** $QT_END_LICENSE$ |
|
39 |
** |
|
40 |
****************************************************************************/ |
|
41 |
|
|
42 |
#include "qsharedmemory.h" |
|
43 |
#include "qsharedmemory_p.h" |
|
44 |
#include "qsystemsemaphore.h" |
|
45 |
#include <qdir.h> |
|
46 |
#include <qcryptographichash.h> |
|
47 |
#ifdef Q_OS_SYMBIAN |
|
48 |
#include <e32const.h> |
|
49 |
#endif |
|
50 |
#include <qdebug.h> |
|
51 |
|
|
52 |
QT_BEGIN_NAMESPACE |
|
53 |
|
|
54 |
#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE)) |
|
55 |
/*! |
|
56 |
\internal |
|
57 |
|
|
58 |
Generate a string from the key which can be any unicode string into |
|
59 |
the subset that the win/unix kernel allows. |
|
60 |
|
|
61 |
On Unix this will be a file name |
|
62 |
On Symbian key will be truncated to 80 characters |
|
63 |
*/ |
|
64 |
QString |
|
65 |
QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, |
|
66 |
const QString &prefix) |
|
67 |
{ |
|
68 |
if (key.isEmpty()) |
|
69 |
return QString(); |
|
70 |
|
|
71 |
QString result = prefix; |
|
72 |
|
|
73 |
QString part1 = key; |
|
74 |
part1.replace(QRegExp(QLatin1String("[^A-Za-z]")), QString()); |
|
75 |
result.append(part1); |
|
76 |
|
|
77 |
QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex(); |
|
78 |
result.append(QLatin1String(hex)); |
|
79 |
#ifdef Q_OS_WIN |
|
80 |
return result; |
| 6c08eef by mread at 2010-10-22 |
81 |
#elif defined(Q_OS_SYMBIAN) |
|
82 |
return result.left(KMaxKernelName); |
| d869e1a by Ritt Konstantin at 2011-06-21 |
83 |
#elif defined(QT_POSIX_IPC) |
|
84 |
return QLatin1Char('/') + result; |
| 8f427b2 by axis at 2009-04-24 |
85 |
#else |
|
86 |
return QDir::tempPath() + QLatin1Char('/') + result; |
|
87 |
#endif |
|
88 |
} |
|
89 |
#endif // QT_NO_SHAREDMEMORY && QT_NO_SHAREDMEMORY |
|
90 |
|
|
91 |
#ifndef QT_NO_SHAREDMEMORY |
|
92 |
|
|
93 |
/*! |
|
94 |
\class QSharedMemory |
|
95 |
\since 4.4 |
|
96 |
|
|
97 |
\brief The QSharedMemory class provides access to a shared memory segment. |
|
98 |
|
|
99 |
QSharedMemory provides access to a shared memory segment by multiple |
|
100 |
threads and processes. It also provides a way for a single thread or |
|
101 |
process to lock the memory for exclusive access. |
|
102 |
|
|
103 |
When using this class, be aware of the following platform |
|
104 |
differences: |
|
105 |
|
|
106 |
\list |
|
107 |
|
|
108 |
\o Windows: QSharedMemory does not "own" the shared memory segment. |
|
109 |
When all threads or processes that have an instance of QSharedMemory |
|
110 |
attached to a particular shared memory segment have either destroyed |
|
111 |
their instance of QSharedMemory or exited, the Windows kernel |
|
112 |
releases the shared memory segment automatically. |
|
113 |
|
|
114 |
\o Unix: QSharedMemory "owns" the shared memory segment. When the |
|
115 |
last thread or process that has an instance of QSharedMemory |
|
116 |
attached to a particular shared memory segment detaches from the |
|
117 |
segment by destroying its instance of QSharedMemory, the Unix kernel |
|
118 |
release the shared memory segment. But if that last thread or |
|
119 |
process crashes without running the QSharedMemory destructor, the |
|
120 |
shared memory segment survives the crash. |
|
121 |
|
| d869e1a by Ritt Konstantin at 2011-06-21 |
122 |
\o QNX: Due to possible race conditions in the POSIX IPC implementation, create() |
|
123 |
should be called prior to any attach() calls (even across multiple threads). |
|
124 |
|
| 8f427b2 by axis at 2009-04-24 |
125 |
\o HP-UX: Only one attach to a shared memory segment is allowed per |
|
126 |
process. This means that QSharedMemory should not be used across |
|
127 |
multiple threads in the same process in HP-UX. |
|
128 |
|
|
129 |
\o Symbian: QSharedMemory does not "own" the shared memory segment. |
|
130 |
When all threads or processes that have an instance of QSharedMemory |
|
131 |
attached to a particular shared memory segment have either destroyed |
|
132 |
their instance of QSharedMemory or exited, the Symbian kernel |
|
133 |
releases the shared memory segment automatically. |
|
134 |
Also, access to a shared memory segment cannot be limited to read-only |
|
135 |
in Symbian. |
|
136 |
|
|
137 |
\endlist |
|
138 |
|
|
139 |
Remember to lock the shared memory with lock() before reading from |
|
140 |
or writing to the shared memory, and remember to release the lock |
|
141 |
with unlock() after you are done. |
|
142 |
|
|
143 |
Unlike QtSharedMemory, QSharedMemory automatically destroys the |
|
144 |
shared memory segment when the last instance of QSharedMemory is |
|
145 |
detached from the segment, and no references to the segment |
|
146 |
remain. Do not mix using QtSharedMemory and QSharedMemory. Port |
|
147 |
everything to QSharedMemory. |
| 9824e4a by Markus Goetz at 2009-05-18 |
148 |
|
| 97a092b by Mirko Damiani at 2010-05-26 |
149 |
\warning QSharedMemory changes the key in a Qt-specific way, unless otherwise |
|
150 |
specified. Interoperation with non-Qt applications is achieved by first creating |
|
151 |
a default shared memory with QSharedMemory() and then setting a native key with |
|
152 |
setNativeKey(). When using native keys, shared memory is not protected against |
|
153 |
multiple accesses on it (e.g. unable to lock()) and a user-defined mechanism |
|
154 |
should be used to achieve a such protection. |
| 8f427b2 by axis at 2009-04-24 |
155 |
*/ |
|
156 |
|
|
157 |
/*! |
|
158 |
\overload QSharedMemory() |
|
159 |
|
|
160 |
Constructs a shared memory object with the given \a parent. The |
|
161 |
shared memory object's key is not set by the constructor, so the |
|
162 |
shared memory object does not have an underlying shared memory |
| 97a092b by Mirko Damiani at 2010-05-26 |
163 |
segment attached. The key must be set with setKey() or setNativeKey() |
|
164 |
before create() or attach() can be used. |
| 8f427b2 by axis at 2009-04-24 |
165 |
|
|
166 |
\sa setKey() |
|
167 |
*/ |
|
168 |
QSharedMemory::QSharedMemory(QObject *parent) |
|
169 |
: QObject(*new QSharedMemoryPrivate, parent) |
|
170 |
{ |
|
171 |
} |
|
172 |
|
|
173 |
/*! |
|
174 |
Constructs a shared memory object with the given \a parent and with |
|
175 |
its key set to \a key. Because its key is set, its create() and |
|
176 |
attach() functions can be called. |
|
177 |
|
|
178 |
\sa setKey(), create(), attach() |
|
179 |
*/ |
|
180 |
QSharedMemory::QSharedMemory(const QString &key, QObject *parent) |
|
181 |
: QObject(*new QSharedMemoryPrivate, parent) |
|
182 |
{ |
|
183 |
setKey(key); |
|
184 |
} |
|
185 |
|
|
186 |
/*! |
|
187 |
The destructor clears the key, which forces the shared memory object |
|
188 |
to \l {detach()} {detach} from its underlying shared memory |
|
189 |
segment. If this shared memory object is the last one connected to |
|
190 |
the shared memory segment, the detach() operation destroys the |
|
191 |
shared memory segment. |
|
192 |
|
|
193 |
\sa detach() isAttached() |
|
194 |
*/ |
|
195 |
QSharedMemory::~QSharedMemory() |
|
196 |
{ |
|
197 |
setKey(QString()); |
|
198 |
} |
|
199 |
|
|
200 |
/*! |
| 8d267e8 by Andreas Aardal Hanssen at 2010-05-26 |
201 |
Sets the platform independent \a key for this shared memory object. If \a key |
|
202 |
is the same as the current key, the function returns without doing anything. |
|
203 |
|
|
204 |
You can call key() to retrieve the platform independent key. Internally, |
|
205 |
QSharedMemory converts this key into a platform specific key. If you instead |
|
206 |
call nativeKey(), you will get the platform specific, converted key. |
|
207 |
|
|
208 |
If the shared memory object is attached to an underlying shared memory |
|
209 |
segment, it will \l {detach()} {detach} from it before setting the new key. |
| 97a092b by Mirko Damiani at 2010-05-26 |
210 |
This function does not do an attach(). |
|
211 |
|
|
212 |
\sa key() nativeKey() isAttached() |
|
213 |
*/ |
| 8f427b2 by axis at 2009-04-24 |
214 |
void QSharedMemory::setKey(const QString &key) |
|
215 |
{ |
|
216 |
Q_D(QSharedMemory); |
| 97a092b by Mirko Damiani at 2010-05-26 |
217 |
if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey) |
| 8f427b2 by axis at 2009-04-24 |
218 |
return; |
|
219 |
|
|
220 |
if (isAttached()) |
|
221 |
detach(); |
|
222 |
d->cleanHandle(); |
|
223 |
d->key = key; |
| 97a092b by Mirko Damiani at 2010-05-26 |
224 |
d->nativeKey = d->makePlatformSafeKey(key); |
|
225 |
} |
|
226 |
|
|
227 |
/*! |
| 8d267e8 by Andreas Aardal Hanssen at 2010-05-26 |
228 |
\since 4.8 |
|
229 |
|
|
230 |
Sets the native, platform specific, \a key for this shared memory object. If |
|
231 |
\a key is the same as the current native key, the function returns without |
|
232 |
doing anything. If all you want is to assign a key to a segment, you should |
|
233 |
call setKey() instead. |
|
234 |
|
|
235 |
You can call nativeKey() to retrieve the native key. If a native key has been |
|
236 |
assigned, calling key() will return a null string. |
|
237 |
|
|
238 |
If the shared memory object is attached to an underlying shared memory |
| 97a092b by Mirko Damiani at 2010-05-26 |
239 |
segment, it will \l {detach()} {detach} from it before setting the new key. |
|
240 |
This function does not do an attach(). |
|
241 |
|
| 8d267e8 by Andreas Aardal Hanssen at 2010-05-26 |
242 |
The application will not be portable if you set a native key. |
|
243 |
|
| 97a092b by Mirko Damiani at 2010-05-26 |
244 |
\sa nativeKey() key() isAttached() |
|
245 |
*/ |
|
246 |
void QSharedMemory::setNativeKey(const QString &key) |
|
247 |
{ |
|
248 |
Q_D(QSharedMemory); |
|
249 |
if (key == d->nativeKey && d->key.isNull()) |
|
250 |
return; |
|
251 |
|
|
252 |
if (isAttached()) |
|
253 |
detach(); |
|
254 |
d->cleanHandle(); |
| 11bacd3 by Ritt Konstantin at 2011-06-06 |
255 |
d->key.clear(); |
| 97a092b by Mirko Damiani at 2010-05-26 |
256 |
d->nativeKey = key; |
| 8f427b2 by axis at 2009-04-24 |
257 |
} |
|
258 |
|
|
259 |
bool QSharedMemoryPrivate::initKey() |
|
260 |
{ |
| 8eaf39f by Ritt Konstantin at 2011-06-06 |
261 |
cleanHandle(); |
|
262 |
|
| 8f427b2 by axis at 2009-04-24 |
263 |
#ifndef QT_NO_SYSTEMSEMAPHORE |
|
264 |
systemSemaphore.setKey(QString(), 1); |
|
265 |
systemSemaphore.setKey(key, 1); |
|
266 |
if (systemSemaphore.error() != QSystemSemaphore::NoError) { |
|
267 |
QString function = QLatin1String("QSharedMemoryPrivate::initKey"); |
|
268 |
errorString = QSharedMemory::tr("%1: unable to set key on lock").arg(function); |
|
269 |
switch(systemSemaphore.error()) { |
|
270 |
case QSystemSemaphore::PermissionDenied: |
|
271 |
error = QSharedMemory::PermissionDenied; |
|
272 |
break; |
|
273 |
case QSystemSemaphore::KeyError: |
|
274 |
error = QSharedMemory::KeyError; |
|
275 |
break; |
|
276 |
case QSystemSemaphore::AlreadyExists: |
|
277 |
error = QSharedMemory::AlreadyExists; |
|
278 |
break; |
|
279 |
case QSystemSemaphore::NotFound: |
|
280 |
error = QSharedMemory::NotFound; |
|
281 |
break; |
|
282 |
case QSystemSemaphore::OutOfResources: |
|
283 |
error = QSharedMemory::OutOfResources; |
|
284 |
break; |
|
285 |
case QSystemSemaphore::UnknownError: |
|
286 |
default: |
|
287 |
error = QSharedMemory::UnknownError; |
|
288 |
break; |
|
289 |
} |
|
290 |
return false; |
|
291 |
} |
|
292 |
#endif |
| 11bacd3 by Ritt Konstantin at 2011-06-06 |
293 |
errorString.clear(); |
| 8f427b2 by axis at 2009-04-24 |
294 |
error = QSharedMemory::NoError; |
|
295 |
return true; |
|
296 |
} |
|
297 |
|
|
298 |
/*! |
| 8d267e8 by Andreas Aardal Hanssen at 2010-05-26 |
299 |
Returns the key assigned with setKey() to this shared memory, or a null key |
|
300 |
if no key has been assigned, or if the segment is using a nativeKey(). The |
|
301 |
key is the identifier used by Qt applications to identify the shared memory |
|
302 |
segment. |
|
303 |
|
|
304 |
You can find the native, platform specific, key used by the operating system |
|
305 |
by calling nativeKey(). |
| 97a092b by Mirko Damiani at 2010-05-26 |
306 |
|
|
307 |
\sa setKey() setNativeKey() |
| 8f427b2 by axis at 2009-04-24 |
308 |
*/ |
|
309 |
QString QSharedMemory::key() const |
|
310 |
{ |
|
311 |
Q_D(const QSharedMemory); |
|
312 |
return d->key; |
|
313 |
} |
|
314 |
|
|
315 |
/*! |
| 8d267e8 by Andreas Aardal Hanssen at 2010-05-26 |
316 |
\since 4.8 |
|
317 |
|
|
318 |
Returns the native, platform specific, key for this shared memory object. The |
|
319 |
native key is the identifier used by the operating system to identify the |
|
320 |
shared memory segment. |
|
321 |
|
|
322 |
You can use the native key to access shared memory segments that have not |
|
323 |
been created by Qt, or to grant shared memory access to non-Qt applications. |
| 97a092b by Mirko Damiani at 2010-05-26 |
324 |
|
|
325 |
\sa setKey() setNativeKey() |
|
326 |
*/ |
|
327 |
QString QSharedMemory::nativeKey() const |
|
328 |
{ |
|
329 |
Q_D(const QSharedMemory); |
|
330 |
return d->nativeKey; |
|
331 |
} |
|
332 |
|
|
333 |
/*! |
|
334 |
Creates a shared memory segment of \a size bytes with the key passed to the |
|
335 |
constructor, set with setKey() or set with setNativeKey(), then attaches to |
|
336 |
the new shared memory segment with the given access \a mode and returns |
|
337 |
\tt true. If a shared memory segment identified by the key already exists, |
|
338 |
the attach operation is not performed and \tt false is returned. When the |
|
339 |
return value is \tt false, call error() to determine which error occurred. |
| 8f427b2 by axis at 2009-04-24 |
340 |
|
|
341 |
\sa error() |
|
342 |
*/ |
|
343 |
bool QSharedMemory::create(int size, AccessMode mode) |
|
344 |
{ |
|
345 |
Q_D(QSharedMemory); |
|
346 |
|
|
347 |
if (!d->initKey()) |
|
348 |
return false; |
|
349 |
|
| 11bacd3 by Ritt Konstantin at 2011-06-06 |
350 |
if (size <= 0) { |
|
351 |
d->error = QSharedMemory::InvalidSize; |
|
352 |
d->errorString = QSharedMemory::tr("%1: create size is less then 0").arg(QLatin1String("QSharedMemory::create")); |
|
353 |
return false; |
|
354 |
} |
|
355 |
|
| 8f427b2 by axis at 2009-04-24 |
356 |
#ifndef QT_NO_SYSTEMSEMAPHORE |
|
357 |
#ifndef Q_OS_WIN |
|
358 |
// Take ownership and force set initialValue because the semaphore |
|
359 |
// might have already existed from a previous crash. |
|
360 |
d->systemSemaphore.setKey(d->key, 1, QSystemSemaphore::Create); |
|
361 |
#endif |
|
362 |
|
|
363 |
QSharedMemoryLocker lock(this); |
| 11bacd3 by Ritt Konstantin at 2011-06-06 |
364 |
if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::create"))) |
| 8f427b2 by axis at 2009-04-24 |
365 |
return false; |
|
366 |
#endif |
|
367 |
|
|
368 |
if (!d->create(size)) |
|
369 |
return false; |
|
370 |
|
|
371 |
return d->attach(mode); |
|
372 |
} |
|
373 |
|
|
374 |
/*! |
|
375 |
Returns the size of the attached shared memory segment. If no shared |
|
376 |
memory segment is attached, 0 is returned. |
|
377 |
|
|
378 |
\sa create() attach() |
|
379 |
*/ |
|
380 |
int QSharedMemory::size() const |
|
381 |
{ |
|
382 |
Q_D(const QSharedMemory); |
|
383 |
return d->size; |
|
384 |
} |
|
385 |
|
|
386 |
/*! |
|
387 |
\enum QSharedMemory::AccessMode |
|
388 |
|
|
389 |
\value ReadOnly The shared memory segment is read-only. Writing to |
|
390 |
the shared memory segment is not allowed. An attempt to write to a |
|
391 |
shared memory segment created with ReadOnly causes the program to |
|
392 |
abort. |
|
393 |
|
|
394 |
\value ReadWrite Reading and writing the shared memory segment are |
|
395 |
both allowed. |
|
396 |
*/ |
|
397 |
|
|
398 |
/*! |
|
399 |
Attempts to attach the process to the shared memory segment |
|
400 |
identified by the key that was passed to the constructor or to a |
| 97a092b by Mirko Damiani at 2010-05-26 |
401 |
call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::} |
| 8f427b2 by axis at 2009-04-24 |
402 |
{ReadWrite} by default. It can also be \l {QSharedMemory::} |
|
403 |
{ReadOnly}. Returns true if the attach operation is successful. If |
|
404 |
false is returned, call error() to determine which error occurred. |
|
405 |
After attaching the shared memory segment, a pointer to the shared |
|
406 |
memory can be obtained by calling data(). |
|
407 |
|
|
408 |
\sa isAttached(), detach(), create() |
|
409 |
*/ |
|
410 |
bool QSharedMemory::attach(AccessMode mode) |
|
411 |
{ |
|
412 |
Q_D(QSharedMemory); |
|
413 |
|
|
414 |
if (isAttached() || !d->initKey()) |
|
415 |
return false; |
|
416 |
#ifndef QT_NO_SYSTEMSEMAPHORE |
|
417 |
QSharedMemoryLocker lock(this); |
| 97a092b by Mirko Damiani at 2010-05-26 |
418 |
if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) |
| 8f427b2 by axis at 2009-04-24 |
419 |
return false; |
|
420 |
#endif |
|
421 |
|
|
422 |
if (isAttached() || !d->handle()) |
|
423 |
return false; |
|
424 |
|
|
425 |
return d->attach(mode); |
|
426 |
} |
|
427 |
|
|
428 |
/*! |
|
429 |
Returns true if this process is attached to the shared memory |
|
430 |
segment. |
|
431 |
|
|
432 |
\sa attach(), detach() |
|
433 |
*/ |
|
434 |
bool QSharedMemory::isAttached() const |
|
435 |
{ |
|
436 |
Q_D(const QSharedMemory); |
|
437 |
return (0 != d->memory); |
|
438 |
} |
|
439 |
|
|
440 |
/*! |
|
441 |
Detaches the process from the shared memory segment. If this was the |
|
442 |
last process attached to the shared memory segment, then the shared |
|
443 |
memory segment is released by the system, i.e., the contents are |
|
444 |
destroyed. The function returns true if it detaches the shared |
|
445 |
memory segment. If it returns false, it usually means the segment |
|
446 |
either isn't attached, or it is locked by another process. |
|
447 |
|
|
448 |
\sa attach(), isAttached() |
|
449 |
*/ |
|
450 |
bool QSharedMemory::detach() |
|
451 |
{ |
|
452 |
Q_D(QSharedMemory); |
|
453 |
if (!isAttached()) |
|
454 |
return false; |
|
455 |
|
|
456 |
#ifndef QT_NO_SYSTEMSEMAPHORE |
|
457 |
QSharedMemoryLocker lock(this); |
| 97a092b by Mirko Damiani at 2010-05-26 |
458 |
if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) |
| 8f427b2 by axis at 2009-04-24 |
459 |
return false; |
|
460 |
#endif |
|
461 |
|
| c17e49e by Ritt Konstantin at 2011-01-21 |
462 |
return d->detach(); |
| 8f427b2 by axis at 2009-04-24 |
463 |
} |
|
464 |
|
|
465 |
/*! |
|
466 |
Returns a pointer to the contents of the shared memory segment, if |
|
467 |
one is attached. Otherwise it returns null. Remember to lock the |
|
468 |
shared memory with lock() before reading from or writing to the |
|
469 |
shared memory, and remember to release the lock with unlock() after |
|
470 |
you are done. |
|
471 |
|
|
472 |
\sa attach() |
|
473 |
*/ |
|
474 |
void *QSharedMemory::data() |
|
475 |
{ |
|
476 |
Q_D(QSharedMemory); |
|
477 |
return d->memory; |
|
478 |
} |
|
479 |
|
|
480 |
/*! |
|
481 |
Returns a const pointer to the contents of the shared memory |
|
482 |
segment, if one is attached. Otherwise it returns null. Remember to |
|
483 |
lock the shared memory with lock() before reading from or writing to |
|
484 |
the shared memory, and remember to release the lock with unlock() |
|
485 |
after you are done. |
|
486 |
|
|
487 |
\sa attach() create() |
|
488 |
*/ |
|
489 |
const void* QSharedMemory::constData() const |
|
490 |
{ |
|
491 |
Q_D(const QSharedMemory); |
|
492 |
return d->memory; |
|
493 |
} |
|
494 |
|
|
495 |
/*! |
|
496 |
\overload data() |
|
497 |
*/ |
|
498 |
const void *QSharedMemory::data() const |
|
499 |
{ |
|
500 |
Q_D(const QSharedMemory); |
|
501 |
return d->memory; |
|
502 |
} |
|
503 |
|
|
504 |
#ifndef QT_NO_SYSTEMSEMAPHORE |
|
505 |
/*! |
|
506 |
This is a semaphore that locks the shared memory segment for access |
|
507 |
by this process and returns true. If another process has locked the |
|
508 |
segment, this function blocks until the lock is released. Then it |
|
509 |
acquires the lock and returns true. If this function returns false, |
| 97a092b by Mirko Damiani at 2010-05-26 |
510 |
it means that you have ignored a false return from create() or attach(), |
|
511 |
that you have set the key with setNativeKey() or that |
|
512 |
QSystemSemaphore::acquire() failed due to an unknown system error. |
| 8f427b2 by axis at 2009-04-24 |
513 |
|
|
514 |
\sa unlock(), data(), QSystemSemaphore::acquire() |
|
515 |
*/ |
|
516 |
bool QSharedMemory::lock() |
|
517 |
{ |
|
518 |
Q_D(QSharedMemory); |
|
519 |
if (d->lockedByMe) { |
|
520 |
qWarning("QSharedMemory::lock: already locked"); |
|
521 |
return true; |
|
522 |
} |
|
523 |
if (d->systemSemaphore.acquire()) { |
|
524 |
d->lockedByMe = true; |
|
525 |
return true; |
|
526 |
} |
|
527 |
QString function = QLatin1String("QSharedMemory::lock"); |
|
528 |
d->errorString = QSharedMemory::tr("%1: unable to lock").arg(function); |
|
529 |
d->error = QSharedMemory::LockError; |
|
530 |
return false; |
|
531 |
} |
|
532 |
|
|
533 |
/*! |
|
534 |
Releases the lock on the shared memory segment and returns true, if |
|
535 |
the lock is currently held by this process. If the segment is not |
|
536 |
locked, or if the lock is held by another process, nothing happens |
|
537 |
and false is returned. |
|
538 |
|
|
539 |
\sa lock() |
|
540 |
*/ |
|
541 |
bool QSharedMemory::unlock() |
|
542 |
{ |
|
543 |
Q_D(QSharedMemory); |
|
544 |
if (!d->lockedByMe) |
|
545 |
return false; |
|
546 |
d->lockedByMe = false; |
|
547 |
if (d->systemSemaphore.release()) |
|
548 |
return true; |
|
549 |
QString function = QLatin1String("QSharedMemory::unlock"); |
|
550 |
d->errorString = QSharedMemory::tr("%1: unable to unlock").arg(function); |
|
551 |
d->error = QSharedMemory::LockError; |
|
552 |
return false; |
|
553 |
} |
|
554 |
#endif // QT_NO_SYSTEMSEMAPHORE |
|
555 |
|
|
556 |
/*! |
|
557 |
\enum QSharedMemory::SharedMemoryError |
|
558 |
|
|
559 |
\value NoError No error occurred. |
|
560 |
|
|
561 |
\value PermissionDenied The operation failed because the caller |
|
562 |
didn't have the required permissions. |
|
563 |
|
|
564 |
\value InvalidSize A create operation failed because the requested |
|
565 |
size was invalid. |
|
566 |
|
|
567 |
\value KeyError The operation failed because of an invalid key. |
|
568 |
|
|
569 |
\value AlreadyExists A create() operation failed because a shared |
|
570 |
memory segment with the specified key already existed. |
|
571 |
|
|
572 |
\value NotFound An attach() failed because a shared memory segment |
|
573 |
with the specified key could not be found. |
|
574 |
|
|
575 |
\value LockError The attempt to lock() the shared memory segment |
|
576 |
failed because create() or attach() failed and returned false, or |
|
577 |
because a system error occurred in QSystemSemaphore::acquire(). |
|
578 |
|
|
579 |
\value OutOfResources A create() operation failed because there was |
|
580 |
not enough memory available to fill the request. |
|
581 |
|
|
582 |
\value UnknownError Something else happened and it was bad. |
|
583 |
*/ |
|
584 |
|
|
585 |
/*! |
|
586 |
Returns a value indicating whether an error occurred, and, if so, |
|
587 |
which error it was. |
|
588 |
|
|
589 |
\sa errorString() |
|
590 |
*/ |
|
591 |
QSharedMemory::SharedMemoryError QSharedMemory::error() const |
|
592 |
{ |
|
593 |
Q_D(const QSharedMemory); |
|
594 |
return d->error; |
|
595 |
} |
|
596 |
|
|
597 |
/*! |
|
598 |
Returns a text description of the last error that occurred. If |
|
599 |
error() returns an \l {QSharedMemory::SharedMemoryError} {error |
|
600 |
value}, call this function to get a text string that describes the |
|
601 |
error. |
|
602 |
|
|
603 |
\sa error() |
|
604 |
*/ |
|
605 |
QString QSharedMemory::errorString() const |
|
606 |
{ |
|
607 |
Q_D(const QSharedMemory); |
|
608 |
return d->errorString; |
|
609 |
} |
|
610 |
|
|
611 |
#endif // QT_NO_SHAREDMEMORY |
|
612 |
|
|
613 |
QT_END_NAMESPACE |