1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 ** This file is part of a Qt Solutions component.
10 ** You may use this file under the terms of the BSD license as follows:
12 ** "Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
15 ** * Redistributions of source code must retain the above copyright
16 ** notice, this list of conditions and the following disclaimer.
17 ** * Redistributions in binary form must reproduce the above copyright
18 ** notice, this list of conditions and the following disclaimer in
19 ** the documentation and/or other materials provided with the
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22 ** the names of its contributors may be used to endorse or promote
23 ** products derived from this software without specific prior written
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
38 ****************************************************************************/
40 #include "qtlockedfile.h"
41 #include <qt_windows.h>
42 #include <QtCore/QFileInfo>
44 #define MUTEX_PREFIX "QtLockedFile mutex "
45 // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
46 #define MAX_READERS MAXIMUM_WAIT_OBJECTS
48 Qt::HANDLE
QtLockedFile::getMutexHandle(int idx
, bool doCreate
)
50 if (mutexname
.isEmpty()) {
52 mutexname
= QString::fromLatin1(MUTEX_PREFIX
)
53 + fi
.absoluteFilePath().toLower();
55 QString
mname(mutexname
);
57 mname
+= QString::number(idx
);
61 QT_WA( { mutex
= CreateMutexW(NULL
, FALSE
, (TCHAR
*)mname
.utf16()); },
62 { mutex
= CreateMutexA(NULL
, FALSE
, mname
.toLocal8Bit().constData()); } );
64 qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
69 QT_WA( { mutex
= OpenMutexW(SYNCHRONIZE
| MUTEX_MODIFY_STATE
, FALSE
, (TCHAR
*)mname
.utf16()); },
70 { mutex
= OpenMutexA(SYNCHRONIZE
| MUTEX_MODIFY_STATE
, FALSE
, mname
.toLocal8Bit().constData()); } );
72 if (GetLastError() != ERROR_FILE_NOT_FOUND
)
73 qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
80 bool QtLockedFile::waitMutex(Qt::HANDLE mutex
, bool doBlock
)
83 DWORD res
= WaitForSingleObject(mutex
, doBlock
? INFINITE
: 0);
92 qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
99 bool QtLockedFile::lock(LockMode mode
, bool block
)
102 qWarning("QtLockedFile::lock(): file is not opened");
109 if (mode
== m_lock_mode
)
112 if (m_lock_mode
!= NoLock
)
115 if (!wmutex
&& !(wmutex
= getMutexHandle(-1, true)))
118 if (!waitMutex(wmutex
, block
))
121 if (mode
== ReadLock
) {
123 for (; idx
< MAX_READERS
; idx
++) {
124 rmutex
= getMutexHandle(idx
, false);
125 if (!rmutex
|| waitMutex(rmutex
, false))
130 if (idx
>= MAX_READERS
) {
131 qWarning("QtLockedFile::lock(): too many readers");
136 rmutex
= getMutexHandle(idx
, true);
137 if (!rmutex
|| !waitMutex(rmutex
, false))
144 ReleaseMutex(wmutex
);
149 Q_ASSERT(rmutexes
.isEmpty());
150 for (int i
= 0; i
< MAX_READERS
; i
++) {
151 Qt::HANDLE mutex
= getMutexHandle(i
, false);
153 rmutexes
.append(mutex
);
155 if (rmutexes
.size()) {
156 DWORD res
= WaitForMultipleObjects(rmutexes
.size(), rmutexes
.constData(),
157 TRUE
, block
? INFINITE
: 0);
158 if (res
!= WAIT_OBJECT_0
&& res
!= WAIT_ABANDONED
) {
159 if (res
!= WAIT_TIMEOUT
)
160 qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
161 m_lock_mode
= WriteLock
; // trick unlock() to clean up - semiyucky
172 bool QtLockedFile::unlock()
175 qWarning("QtLockedFile::unlock(): file is not opened");
182 if (m_lock_mode
== ReadLock
) {
183 ReleaseMutex(rmutex
);
188 foreach(Qt::HANDLE mutex
, rmutexes
) {
193 ReleaseMutex(wmutex
);
196 m_lock_mode
= QtLockedFile::NoLock
;
200 QtLockedFile::~QtLockedFile()