summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qtipc/qsharedmemory/src
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel/qtipc/qsharedmemory/src')
-rw-r--r--tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.cpp246
-rw-r--r--tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.h135
-rw-r--r--tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_p.h109
-rw-r--r--tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_unix.cpp234
-rw-r--r--tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_win.cpp183
-rw-r--r--tests/auto/corelib/kernel/qtipc/qsharedmemory/src/src.pri11
6 files changed, 918 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.cpp b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.cpp
new file mode 100644
index 0000000000..b48bd7bebe
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qsystemlock.h"
+#include "qsystemlock_p.h"
+
+#include <qdebug.h>
+
+/*! \class QSystemLocker
+
+ \brief The QSystemLocker class is a convenience class that simplifies
+ locking and unlocking system locks.
+
+ The purpose of QSystemLocker is to simplify QSystemLock locking and
+ unlocking. Locking and unlocking a QSystemLock in complex functions and
+ statements or in exception handling code is error-prone and difficult to
+ debug. QSystemLocker can be used in such situations to ensure that the
+ state of the locks is always well-defined.
+
+ QSystemLocker should be created within a function where a QSystemLock needs
+ to be locked. The system lock is locked when QSystemLocker is created. If
+ locked, the system lock will be unlocked when the QSystemLocker is
+ destroyed. QSystemLocker can be unlocked with unlock() and relocked with
+ relock().
+
+ \sa QSystemLock
+ */
+
+/*! \fn QSystemLocker::QSystemLocker()
+
+ Constructs a QSystemLocker and locks \a lock. The \a lock will be
+ unlocked when the QSystemLocker is destroyed. If lock is zero,
+ QSystemLocker does nothing.
+
+ \sa QSystemLock::lock()
+ */
+
+/*! \fn QSystemLocker::~QSystemLocker()
+
+ Destroys the QSystemLocker and unlocks it if it was
+ locked in the constructor.
+
+ \sa QSystemLock::unlock()
+ */
+
+/*! \fn QSystemLocker::systemLock()
+
+ Returns a pointer to the lock that was locked in the constructor.
+ */
+
+/*! \fn QSystemLocker::relock()
+
+ Relocks an unlocked locker.
+
+ \sa unlock()
+ */
+
+/*! \fn QSystemLocker::unlock()
+
+ Unlocks this locker. You can use relock() to lock it again.
+ It does not need to be locked when destroyed.
+
+ \sa relock()
+ */
+
+/*! \class QSystemLock
+
+ \brief The QSystemLock class provides a system wide lock
+ that can be used between threads or processes.
+
+ The purpose of a QSystemLocker is to protect an object that can be
+ accessed by multiple threads or processes such as shared memory or a file.
+
+ For example, say there is a method which prints a message to a log file:
+
+ void log(const QString &logText)
+ {
+ QSystemLock systemLock(QLatin1String("logfile"));
+ systemLock.lock();
+ QFile file(QDir::temp() + QLatin1String("/log"));
+ if (file.open(QIODevice::Append)) {
+ QTextStream out(&file);
+ out << logText;
+ }
+ systemLock.unlock();
+ }
+
+ If this is called from two separate processes the resulting log file is
+ guaranteed to contain both lines.
+
+ When you call lock(), other threads or processes that try to call lock()
+ with the same key will block until the thread or process that got the lock
+ calls unlock().
+
+ A non-blocking alternative to lock() is tryLock().
+ */
+
+/*!
+ Constructs a new system lock with \a key. The lock is created in an
+ unlocked state.
+
+ \sa lock(), key().
+ */
+QSystemLock::QSystemLock(const QString &key)
+{
+ d = new QSystemLockPrivate;
+ setKey(key);
+}
+
+/*!
+ Destroys a system lock.
+
+ warning: This will not unlock the system lock if it has been locked.
+*/
+QSystemLock::~QSystemLock()
+{
+ d->cleanHandle();
+ delete d;
+}
+
+/*!
+ Sets a new key to this system lock.
+
+ \sa key()
+ */
+void QSystemLock::setKey(const QString &key)
+{
+ if (key == d->key)
+ return;
+ d->cleanHandle();
+ d->lockCount = 0;
+ d->key = key;
+ // cache the file name so it doesn't have to be generated all the time.
+ d->fileName = d->makeKeyFileName();
+ d->error = QSystemLock::NoError;
+ d->errorString = QString();
+ d->handle();
+}
+
+/*!
+ Returns the key assigned to this system lock
+
+ \sa setKey()
+ */
+QString QSystemLock::key() const
+{
+ return d->key;
+}
+
+/*!
+ Locks the system lock. Lock \a mode can either be ReadOnly or ReadWrite.
+ If a mode is ReadOnly, attempts by other processes to obtain
+ ReadOnly locks will succeed, and ReadWrite attempts will block until
+ all of the ReadOnly locks are unlocked. If locked as ReadWrite, all
+ other attempts to lock will block until the lock is unlocked. A given
+ QSystemLock can be locked multiple times without blocking, and will
+ only be unlocked after a corresponding number of unlock()
+ calls are made. Returns true on success; otherwise returns false.
+
+ \sa unlock(), tryLock()
+ */
+bool QSystemLock::lock(LockMode mode)
+{
+ if (d->lockCount > 0 && mode == ReadOnly && d->lockedMode == ReadWrite) {
+ qWarning() << "QSystemLock::lock readwrite lock on top of readonly lock.";
+ return false;
+ }
+ return d->modifySemaphore(QSystemLockPrivate::Lock, mode);
+}
+
+/*!
+ Unlocks the system lock.
+ Returns true on success; otherwise returns false.
+
+ \sa lock()
+ */
+bool QSystemLock::unlock()
+{
+ if (d->lockCount == 0) {
+ qWarning() << "QSystemLock::unlock: unlock with no lock.";
+ return false;
+ }
+ return d->modifySemaphore(QSystemLockPrivate::Unlock, d->lockedMode);
+}
+
+/*!
+ Returns the type of error that occurred last or NoError.
+
+ \sa errorString()
+ */
+QSystemLock::SystemLockError QSystemLock::error() const
+{
+ return d->error;
+}
+
+/*!
+ Returns the human-readable message appropriate to the current error
+ reported by error(). If no suitable string is available, an empty
+ string is returned.
+
+ \sa error()
+ */
+QString QSystemLock::errorString() const
+{
+ return d->errorString;
+}
+
diff --git a/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.h b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.h
new file mode 100644
index 0000000000..f9db4f879c
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QSYSTEMLOCK_H
+#define QSYSTEMLOCK_H
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+#ifndef QT_NO_SYSTEMLOCK
+
+QT_FORWARD_DECLARE_CLASS(QSystemLockPrivate)
+
+class QSystemLock
+{
+
+public:
+ enum SystemLockError
+ {
+ NoError,
+ UnknownError
+ };
+
+ QSystemLock(const QString &key);
+ ~QSystemLock();
+
+ void setKey(const QString &key);
+ QString key() const;
+
+ enum LockMode
+ {
+ ReadOnly,
+ ReadWrite
+ };
+
+ bool lock(LockMode mode = ReadWrite);
+ bool unlock();
+
+ SystemLockError error() const;
+ QString errorString() const;
+
+private:
+ Q_DISABLE_COPY(QSystemLock)
+
+ QSystemLockPrivate *d;
+};
+
+class QSystemLocker
+{
+
+public:
+ inline QSystemLocker(QSystemLock *systemLock,
+ QSystemLock::LockMode mode = QSystemLock::ReadWrite) : q_lock(systemLock)
+ {
+ autoUnLocked = relock(mode);
+ }
+
+ inline ~QSystemLocker()
+ {
+ if (autoUnLocked)
+ unlock();
+ }
+
+ inline QSystemLock *systemLock() const
+ {
+ return q_lock;
+ }
+
+ inline bool relock(QSystemLock::LockMode mode = QSystemLock::ReadWrite)
+ {
+ return (q_lock && q_lock->lock(mode));
+ }
+
+ inline bool unlock()
+ {
+ if (q_lock && q_lock->unlock()) {
+ autoUnLocked = false;
+ return true;
+ }
+ return false;
+ }
+
+private:
+ Q_DISABLE_COPY(QSystemLocker)
+
+ bool autoUnLocked;
+ QSystemLock *q_lock;
+};
+
+#endif // QT_NO_SYSTEMLOCK
+
+QT_END_HEADER
+
+#endif // QSYSTEMLOCK_H
+
diff --git a/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_p.h b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_p.h
new file mode 100644
index 0000000000..628b005afc
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QSYSTEMLOCK_P_H
+#define QSYSTEMLOCK_P_H
+
+#ifndef QT_NO_SYSTEMLOCK
+
+#include "qsystemlock.h"
+#include "private/qsharedmemory_p.h"
+#ifndef Q_OS_WINCE
+#include <sys/types.h>
+#endif
+
+#define MAX_LOCKS 64
+
+class QSystemLockPrivate
+{
+
+public:
+ QSystemLockPrivate();
+
+ QString makeKeyFileName()
+ {
+ return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemlock_"));
+ }
+
+ void setErrorString(const QString &function);
+
+#ifdef Q_OS_WIN
+ HANDLE handle();
+ bool lock(HANDLE, int count);
+ bool unlock(HANDLE, int count);
+#else
+ key_t handle();
+#endif
+ void cleanHandle();
+
+ enum Operation {
+ Lock,
+ Unlock
+ };
+ bool modifySemaphore(Operation op, QSystemLock::LockMode mode = QSystemLock::ReadOnly);
+
+ QString key;
+ QString fileName;
+#ifdef Q_OS_WIN
+ HANDLE semaphore;
+ HANDLE semaphoreLock;
+#else
+ int semaphore;
+#endif
+ int lockCount;
+ QSystemLock::LockMode lockedMode;
+
+ QSystemLock::SystemLockError error;
+ QString errorString;
+
+private:
+#ifndef Q_OS_WIN
+ key_t unix_key;
+ bool createdFile;
+ bool createdSemaphore;
+#endif
+};
+
+#endif // QT_NO_SYSTEMLOCK
+
+#endif // QSYSTEMLOCK_P_H
+
diff --git a/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_unix.cpp b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_unix.cpp
new file mode 100644
index 0000000000..984379619e
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_unix.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qsystemlock.h"
+#include "qsystemlock_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/shm.h>
+#include <unistd.h>
+
+#include <sys/sem.h>
+// We have to define this as on some sem.h will have it
+union qt_semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+};
+
+#define tr(x) QT_TRANSLATE_NOOP(QLatin1String("QSystemLock"), (x))
+
+#if defined(Q_OS_SYMBIAN)
+int createUnixKeyFile(const QString &fileName)
+{
+ if (QFile::exists(fileName))
+ return 0;
+
+ int fd = open(QFile::encodeName(fileName).constData(),
+ O_EXCL | O_CREAT | O_RDWR, 0640);
+ if (-1 == fd) {
+ if (errno == EEXIST)
+ return 0;
+ return -1;
+ } else {
+ close(fd);
+ }
+ return 1;
+}
+#endif
+
+QSystemLockPrivate::QSystemLockPrivate() :
+ semaphore(-1), lockCount(0),
+ error(QSystemLock::NoError), unix_key(-1), createdFile(false), createdSemaphore(false)
+{
+}
+
+void QSystemLockPrivate::setErrorString(const QString &function)
+{
+ switch (errno) {
+ case EIDRM:
+ errorString = function + QLatin1String(": ") + tr("The semaphore set was removed");
+ error = QSystemLock::UnknownError;
+ break;
+ default:
+ errorString = function + QLatin1String(": ") + tr("unknown error");
+ error = QSystemLock::UnknownError;
+ qWarning() << errorString << "key" << key << "errno" << errno << ERANGE << ENOMEM << EINVAL << EINTR << EFBIG << EFAULT << EAGAIN << EACCES << E2BIG;
+ }
+}
+
+/*!
+ \internal
+
+ Setup unix_key
+ */
+key_t QSystemLockPrivate::handle()
+{
+ if (key.isEmpty())
+ return -1;
+
+ // ftok requires that an actual file exists somewhere
+ // If we have already made at some point in the past,
+ // double check that it is still there.
+ if (-1 != unix_key) {
+ int aNewunix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
+ if (aNewunix_key != unix_key) {
+ cleanHandle();
+ } else {
+ return unix_key;
+ }
+ }
+
+ // Create the file needed for ftok
+#if defined(Q_OS_SYMBIAN)
+ int built = createUnixKeyFile(fileName);
+#else
+ int built = QSharedMemoryPrivate::createUnixKeyFile(fileName);
+#endif
+ if (-1 == built)
+ return -1;
+ createdFile = (1 == built);
+
+ // Get the unix key for the created file
+ unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
+ if (-1 == unix_key) {
+ setErrorString(QLatin1String("QSystemLock::handle ftok"));
+ return -1;
+ }
+
+ // Get semaphore
+ semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL);
+ if (-1 == semaphore) {
+ if (errno == EEXIST)
+ semaphore = semget(unix_key, 1, 0666 | IPC_CREAT);
+ if (-1 == semaphore) {
+ setErrorString(QLatin1String("QSystemLock::handle semget"));
+ cleanHandle();
+ return -1;
+ }
+ } else {
+ // Created semaphore, initialize value.
+ createdSemaphore = true;
+ qt_semun init_op;
+ init_op.val = MAX_LOCKS;
+ if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
+ setErrorString(QLatin1String("QSystemLock::handle semctl"));
+ cleanHandle();
+ return -1;
+ }
+ }
+
+ return unix_key;
+}
+
+/*!
+ \internal
+
+ Cleanup the unix_key
+ */
+void QSystemLockPrivate::cleanHandle()
+{
+ unix_key = -1;
+
+ // remove the file if we made it
+ if (createdFile) {
+ if (!QFile::remove(fileName))
+ setErrorString(QLatin1String("QSystemLock::cleanHandle QFile::remove"));
+ createdFile = false;
+ }
+
+ if (createdSemaphore) {
+ if (-1 != semaphore) {
+ if (-1 == semctl(semaphore, 0, IPC_RMID)) {
+ setErrorString(QLatin1String("QSystemLock::cleanHandle semctl"));
+ }
+ semaphore = -1;
+ }
+ createdSemaphore = false;
+ }
+}
+
+/*!
+ \internal
+
+ modifySemaphore generates operation.sem_op and handles recursive behavior.
+ */
+bool QSystemLockPrivate::modifySemaphore(QSystemLockPrivate::Operation op,
+ QSystemLock::LockMode mode)
+{
+ if (-1 == handle())
+ return false;
+
+ if ((lockCount == 0 && op == Lock) || (lockCount > 0 && op == Unlock)) {
+ if (op == Unlock) {
+ --lockCount;
+ if (lockCount < 0)
+ qFatal("%s: lockCount must not be negative", Q_FUNC_INFO);
+ if (lockCount > 0)
+ return true;
+ }
+
+ struct sembuf operation;
+ operation.sem_num = 0;
+ operation.sem_op = (mode == QSystemLock::ReadWrite) ? MAX_LOCKS : 1;
+ if (op == Lock)
+ operation.sem_op *= -1;
+ operation.sem_flg = SEM_UNDO;
+
+ if (-1 == semop(semaphore, &operation, 1)) {
+ setErrorString(QLatin1String("QSystemLock::modify"));
+ return false;
+ }
+ lockedMode = mode;
+ }
+ if (op == Lock)
+ lockCount++;
+
+ return true;
+}
+
diff --git a/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_win.cpp b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_win.cpp
new file mode 100644
index 0000000000..c04b596210
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/qsystemlock_win.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qsystemlock.h"
+#include "qsystemlock_p.h"
+#include <qdebug.h>
+#include <QtCore>
+QSystemLockPrivate::QSystemLockPrivate() :
+ semaphore(0), semaphoreLock(0),
+ lockCount(0), error(QSystemLock::NoError)
+{
+}
+
+void QSystemLockPrivate::setErrorString(const QString &function)
+{
+ BOOL windowsError = GetLastError();
+ if (windowsError == 0)
+ return;
+ errorString = function + QLatin1String(": ")
+ + QLatin1String("Unknown error");
+ error = QSystemLock::UnknownError;
+ qWarning() << errorString << "key" << key << (int)windowsError << semaphore << semaphoreLock;
+}
+
+/*!
+ \internal
+
+ Setup the semaphore
+ */
+HANDLE QSystemLockPrivate::handle()
+{
+ // don't allow making handles on empty keys
+ if (key.isEmpty())
+ return 0;
+
+ // Create it if it doesn't already exists.
+ if (semaphore == 0) {
+ QString safeName = makeKeyFileName();
+ semaphore = CreateSemaphore(0, MAX_LOCKS, MAX_LOCKS, (wchar_t*)safeName.utf16());
+
+ if (semaphore == 0) {
+ setErrorString(QLatin1String("QSystemLockPrivate::handle"));
+ return 0;
+ }
+ }
+
+ if (semaphoreLock == 0) {
+ QString safeLockName = QSharedMemoryPrivate::makePlatformSafeKey(key + QLatin1String("lock"), QLatin1String("qipc_systemlock_"));
+ semaphoreLock = CreateSemaphore(0, 1, 1, (wchar_t*)safeLockName.utf16());
+
+ if (semaphoreLock == 0) {
+ setErrorString(QLatin1String("QSystemLockPrivate::handle"));
+ return 0;
+ }
+ }
+
+ return semaphore;
+}
+
+/*!
+ \internal
+
+ Cleanup the semaphore
+ */
+void QSystemLockPrivate::cleanHandle()
+{
+ if (semaphore && !CloseHandle(semaphore))
+ setErrorString(QLatin1String("QSystemLockPrivate::cleanHandle:"));
+ if (semaphoreLock && !CloseHandle(semaphoreLock))
+ setErrorString(QLatin1String("QSystemLockPrivate::cleanHandle:"));
+ semaphore = 0;
+ semaphoreLock = 0;
+}
+
+bool QSystemLockPrivate::lock(HANDLE handle, int count)
+{
+ if (count == 1) {
+ WaitForSingleObject(handle, INFINITE);
+ return true;
+ }
+
+ int i = count;
+ while (i > 0) {
+ if (WAIT_OBJECT_0 == WaitForSingleObject(handle, 0)) {
+ --i;
+ } else {
+ // undo what we have done, sleep and then try again later
+ ReleaseSemaphore(handle, (count - i), 0);
+ i = count;
+ ReleaseSemaphore(semaphoreLock, 1, 0);
+ Sleep(1);
+ WaitForSingleObject(semaphoreLock, INFINITE);
+ }
+ }
+ return true;
+}
+
+bool QSystemLockPrivate::unlock(HANDLE handle, int count)
+{
+ if (0 == ReleaseSemaphore(handle, count, 0)) {
+ setErrorString(QLatin1String("QSystemLockPrivate::unlock"));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+
+ modifySemaphore handles recursive behavior and modifies the semaphore.
+ */
+bool QSystemLockPrivate::modifySemaphore(QSystemLockPrivate::Operation op,
+ QSystemLock::LockMode mode)
+{
+ if (0 == handle())
+ return false;
+
+ if ((lockCount == 0 && op == Lock) || (lockCount > 0 && op == Unlock)) {
+ if (op == Unlock) {
+ --lockCount;
+ if (lockCount < 0)
+ qFatal("%s: lockCount must not be negative", Q_FUNC_INFO);
+ if (lockCount > 0)
+ return true;
+ }
+
+ int count = (mode == QSystemLock::ReadWrite) ? MAX_LOCKS : 1;
+ if (op == Lock) {
+ lock(semaphoreLock, 1);
+ lock(semaphore, count);
+ if (count != MAX_LOCKS) unlock(semaphoreLock, 1);
+ lockedMode = mode;
+ } else {
+ if (count == MAX_LOCKS) unlock(semaphoreLock, 1);
+ unlock(semaphore, count);
+ }
+
+ }
+ if (op == Lock)
+ lockCount++;
+
+ return true;
+}
+
diff --git a/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/src.pri b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/src.pri
new file mode 100644
index 0000000000..8aaf528447
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtipc/qsharedmemory/src/src.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+QT += core-private
+
+SOURCES += $$PWD/qsystemlock.cpp
+
+HEADERS += $$PWD/qsystemlock.h \
+ $$PWD/qsystemlock_p.h
+
+unix:SOURCES += $$PWD/qsystemlock_unix.cpp
+win32:SOURCES += $$PWD/qsystemlock_win.cpp