1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "qtlockedfile.h"
35 #include <qt_windows.h>
36 #include <QtCore/QFileInfo>
38 namespace SharedTools {
40 #define SEMAPHORE_PREFIX "QtLockedFile semaphore "
41 #define MUTEX_PREFIX "QtLockedFile mutex "
42 #define SEMAPHORE_MAX 100
44 static QString errorCodeToString(DWORD errorCode)
48 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
51 result = QString::fromLocal8Bit(data);
55 if (result.endsWith('\n'))
56 result.truncate(result.length() - 1);
61 bool QtLockedFile::lock(LockMode mode, bool block)
64 qWarning("QtLockedFile::lock(): file is not opened");
68 if (mode == m_lock_mode)
74 if (m_semaphore_hnd == 0) {
76 QString sem_name = QString::fromLatin1(SEMAPHORE_PREFIX)
77 + fi.absoluteFilePath().toLower();
80 m_semaphore_hnd = CreateSemaphoreW(0, SEMAPHORE_MAX, SEMAPHORE_MAX,
81 (TCHAR*)sem_name.utf16());
83 m_semaphore_hnd = CreateSemaphoreA(0, SEMAPHORE_MAX, SEMAPHORE_MAX,
84 sem_name.toLocal8Bit().constData());
87 if (m_semaphore_hnd == 0) {
88 qWarning("QtLockedFile::lock(): CreateSemaphore: %s",
89 errorCodeToString(GetLastError()).toLatin1().constData());
94 bool gotMutex = false;
96 if (mode == ReadLock) {
99 decrement = SEMAPHORE_MAX;
100 if (m_mutex_hnd == 0) {
102 QString mut_name = QString::fromLatin1(MUTEX_PREFIX)
103 + fi.absoluteFilePath().toLower();
105 m_mutex_hnd = CreateMutexW(NULL, FALSE, (TCHAR*)mut_name.utf16());
107 m_mutex_hnd = CreateMutexA(NULL, FALSE, mut_name.toLocal8Bit().constData());
110 if (m_mutex_hnd == 0) {
111 qWarning("QtLockedFile::lock(): CreateMutex: %s",
112 errorCodeToString(GetLastError()).toLatin1().constData());
116 DWORD res = WaitForSingleObject(m_mutex_hnd, block ? INFINITE : 0);
117 if (res == WAIT_TIMEOUT)
119 if (res == WAIT_FAILED) {
120 qWarning("QtLockedFile::lock(): WaitForSingleObject (mutex): %s",
121 errorCodeToString(GetLastError()).toLatin1().constData());
127 for (int i = 0; i < decrement; ++i) {
128 DWORD res = WaitForSingleObject(m_semaphore_hnd, block ? INFINITE : 0);
129 if (res == WAIT_TIMEOUT) {
131 // A failed nonblocking rw locking. Undo changes to semaphore.
132 if (ReleaseSemaphore(m_semaphore_hnd, i, NULL) == 0) {
133 qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s",
134 errorCodeToString(GetLastError()).toLatin1().constData());
139 ReleaseMutex(m_mutex_hnd);
142 if (res != WAIT_OBJECT_0) {
144 ReleaseMutex(m_mutex_hnd);
145 qWarning("QtLockedFile::lock(): WaitForSingleObject (semaphore): %s",
146 errorCodeToString(GetLastError()).toLatin1().constData());
153 ReleaseMutex(m_mutex_hnd);
157 bool QtLockedFile::unlock()
160 qWarning("QtLockedFile::unlock(): file is not opened");
168 if (m_lock_mode == ReadLock)
171 increment = SEMAPHORE_MAX;
173 DWORD ret = ReleaseSemaphore(m_semaphore_hnd, increment, 0);
175 qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s",
176 errorCodeToString(GetLastError()).toLatin1().constData());
180 m_lock_mode = QtLockedFile::NoLock;
184 QtLockedFile::~QtLockedFile()
188 if (m_mutex_hnd != 0) {
189 DWORD ret = CloseHandle(m_mutex_hnd);
191 qWarning("QtLockedFile::~QtLockedFile(): CloseHandle (mutex): %s",
192 errorCodeToString(GetLastError()).toLatin1().constData());
196 if (m_semaphore_hnd != 0) {
197 DWORD ret = CloseHandle(m_semaphore_hnd);
199 qWarning("QtLockedFile::~QtLockedFile(): CloseHandle (semaphore): %s",
200 errorCodeToString(GetLastError()).toLatin1().constData());
206 } // namespace SharedTools