diff options
Diffstat (limited to 'libraries/LocalPeer/src')
-rw-r--r-- | libraries/LocalPeer/src/LocalPeer.cpp | 248 | ||||
-rw-r--r-- | libraries/LocalPeer/src/LockedFile.cpp | 152 | ||||
-rw-r--r-- | libraries/LocalPeer/src/LockedFile.h | 34 | ||||
-rw-r--r-- | libraries/LocalPeer/src/LockedFile_unix.cpp | 96 | ||||
-rw-r--r-- | libraries/LocalPeer/src/LockedFile_win.cpp | 272 |
5 files changed, 401 insertions, 401 deletions
diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp index f71c62d8..129f3abc 100644 --- a/libraries/LocalPeer/src/LocalPeer.cpp +++ b/libraries/LocalPeer/src/LocalPeer.cpp @@ -67,60 +67,60 @@ static const char* ack = "ack"; ApplicationId ApplicationId::fromTraditionalApp() { - QString protoId = QCoreApplication::applicationFilePath(); + QString protoId = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) - protoId = protoId.toLower(); + protoId = protoId.toLower(); #endif - auto prefix = protoId.section(QLatin1Char('/'), -1); - prefix.remove(QRegExp("[^a-zA-Z]")); - prefix.truncate(6); - QByteArray idc = protoId.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - auto socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); + auto prefix = protoId.section(QLatin1Char('/'), -1); + prefix.remove(QRegExp("[^a-zA-Z]")); + prefix.truncate(6); + QByteArray idc = protoId.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + auto socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) - { - QLibrary lib("kernel32"); - pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); - } - if (pProcessIdToSessionId) - { - DWORD sessionId = 0; - pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += QLatin1Char('-') + QString::number(sessionId, 16); - } + if (!pProcessIdToSessionId) + { + QLibrary lib("kernel32"); + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } + if (pProcessIdToSessionId) + { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + socketName += QLatin1Char('-') + QString::number(sessionId, 16); + } #else - socketName += QLatin1Char('-') + QString::number(::getuid(), 16); + socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif - return ApplicationId(socketName); + return ApplicationId(socketName); } ApplicationId ApplicationId::fromPathAndVersion(const QString& dataPath, const QString& version) { - QCryptographicHash shasum(QCryptographicHash::Algorithm::Sha1); - QString result = dataPath + QLatin1Char('-') + version; - shasum.addData(result.toUtf8()); - return ApplicationId(QLatin1String("qtsingleapp-") + QString::fromLatin1(shasum.result().toHex())); + QCryptographicHash shasum(QCryptographicHash::Algorithm::Sha1); + QString result = dataPath + QLatin1Char('-') + version; + shasum.addData(result.toUtf8()); + return ApplicationId(QLatin1String("qtsingleapp-") + QString::fromLatin1(shasum.result().toHex())); } ApplicationId ApplicationId::fromCustomId(const QString& id) { - return ApplicationId(QLatin1String("qtsingleapp-") + id); + return ApplicationId(QLatin1String("qtsingleapp-") + id); } ApplicationId ApplicationId::fromRawString(const QString& id) { - return ApplicationId(id); + return ApplicationId(id); } LocalPeer::LocalPeer(QObject * parent, const ApplicationId &appId) - : QObject(parent), id(appId) + : QObject(parent), id(appId) { - socketName = id.toString(); - server.reset(new QLocalServer()); - QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); - lockFile.reset(new LockedFile(lockName)); - lockFile->open(QIODevice::ReadWrite); + socketName = id.toString(); + server.reset(new QLocalServer()); + QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); + lockFile.reset(new LockedFile(lockName)); + lockFile->open(QIODevice::ReadWrite); } LocalPeer::~LocalPeer() @@ -129,113 +129,113 @@ LocalPeer::~LocalPeer() ApplicationId LocalPeer::applicationId() const { - return id; + return id; } bool LocalPeer::isClient() { - if (lockFile->isLocked()) - return false; + if (lockFile->isLocked()) + return false; - if (!lockFile->lock(LockedFile::WriteLock, false)) - return true; + if (!lockFile->lock(LockedFile::WriteLock, false)) + return true; - bool res = server->listen(socketName); + bool res = server->listen(socketName); #if defined(Q_OS_UNIX) - // ### Workaround - if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); - res = server->listen(socketName); - } + // ### Workaround + if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { + QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); + res = server->listen(socketName); + } #endif - if (!res) - qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); - QObject::connect(server.get(), SIGNAL(newConnection()), SLOT(receiveConnection())); - return false; + if (!res) + qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + QObject::connect(server.get(), SIGNAL(newConnection()), SLOT(receiveConnection())); + return false; } bool LocalPeer::sendMessage(const QString &message, int timeout) { - if (!isClient()) - return false; - - QLocalSocket socket; - bool connOk = false; - for(int i = 0; i < 2; i++) { - // Try twice, in case the other instance is just starting up - socket.connectToServer(socketName); - connOk = socket.waitForConnected(timeout/2); - if (connOk || i) - { - break; - } - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - if (!connOk) - { - return false; - } - - QByteArray uMsg(message.toUtf8()); - QDataStream ds(&socket); - - ds.writeBytes(uMsg.constData(), uMsg.size()); - if(!socket.waitForBytesWritten(timeout)) - { - return false; - } - - // wait for 'ack' - if(!socket.waitForReadyRead(timeout)) - { - return false; - } - - // make sure we got 'ack' - if(!(socket.read(qstrlen(ack)) == ack)) - { - return false; - } - return true; + if (!isClient()) + return false; + + QLocalSocket socket; + bool connOk = false; + for(int i = 0; i < 2; i++) { + // Try twice, in case the other instance is just starting up + socket.connectToServer(socketName); + connOk = socket.waitForConnected(timeout/2); + if (connOk || i) + { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } + if (!connOk) + { + return false; + } + + QByteArray uMsg(message.toUtf8()); + QDataStream ds(&socket); + + ds.writeBytes(uMsg.constData(), uMsg.size()); + if(!socket.waitForBytesWritten(timeout)) + { + return false; + } + + // wait for 'ack' + if(!socket.waitForReadyRead(timeout)) + { + return false; + } + + // make sure we got 'ack' + if(!(socket.read(qstrlen(ack)) == ack)) + { + return false; + } + return true; } void LocalPeer::receiveConnection() { - QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) - { - return; - } - - while (socket->bytesAvailable() < (int)sizeof(quint32)) - { - socket->waitForReadyRead(); - } - QDataStream ds(socket); - QByteArray uMsg; - quint32 remaining; - ds >> remaining; - uMsg.resize(remaining); - int got = 0; - char* uMsgBuf = uMsg.data(); - do - { - got = ds.readRawData(uMsgBuf, remaining); - remaining -= got; - uMsgBuf += got; - } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); - if (got < 0) - { - qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); - delete socket; - return; - } - QString message(QString::fromUtf8(uMsg)); - socket->write(ack, qstrlen(ack)); - socket->waitForBytesWritten(1000); - socket->waitForDisconnected(1000); // make sure client reads ack - delete socket; - emit messageReceived(message); //### (might take a long time to return) + QLocalSocket* socket = server->nextPendingConnection(); + if (!socket) + { + return; + } + + while (socket->bytesAvailable() < (int)sizeof(quint32)) + { + socket->waitForReadyRead(); + } + QDataStream ds(socket); + QByteArray uMsg; + quint32 remaining; + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); + do + { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + if (got < 0) + { + qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); + delete socket; + return; + } + QString message(QString::fromUtf8(uMsg)); + socket->write(ack, qstrlen(ack)); + socket->waitForBytesWritten(1000); + socket->waitForDisconnected(1000); // make sure client reads ack + delete socket; + emit messageReceived(message); //### (might take a long time to return) } diff --git a/libraries/LocalPeer/src/LockedFile.cpp b/libraries/LocalPeer/src/LockedFile.cpp index a4951bfe..73294a16 100644 --- a/libraries/LocalPeer/src/LockedFile.cpp +++ b/libraries/LocalPeer/src/LockedFile.cpp @@ -41,70 +41,70 @@ #include "LockedFile.h" /*! - \class QtLockedFile - - \brief The QtLockedFile class extends QFile with advisory locking - functions. - - A file may be locked in read or write mode. Multiple instances of - \e QtLockedFile, created in multiple processes running on the same - machine, may have a file locked in read mode. Exactly one instance - may have it locked in write mode. A read and a write lock cannot - exist simultaneously on the same file. - - The file locks are advisory. This means that nothing prevents - another process from manipulating a locked file using QFile or - file system functions offered by the OS. Serialization is only - guaranteed if all processes that access the file use - QLockedFile. Also, while holding a lock on a file, a process - must not open the same file again (through any API), or locks - can be unexpectedly lost. - - The lock provided by an instance of \e QtLockedFile is released - whenever the program terminates. This is true even when the - program crashes and no destructors are called. + \class QtLockedFile + + \brief The QtLockedFile class extends QFile with advisory locking + functions. + + A file may be locked in read or write mode. Multiple instances of + \e QtLockedFile, created in multiple processes running on the same + machine, may have a file locked in read mode. Exactly one instance + may have it locked in write mode. A read and a write lock cannot + exist simultaneously on the same file. + + The file locks are advisory. This means that nothing prevents + another process from manipulating a locked file using QFile or + file system functions offered by the OS. Serialization is only + guaranteed if all processes that access the file use + QLockedFile. Also, while holding a lock on a file, a process + must not open the same file again (through any API), or locks + can be unexpectedly lost. + + The lock provided by an instance of \e QtLockedFile is released + whenever the program terminates. This is true even when the + program crashes and no destructors are called. */ /*! \enum QtLockedFile::LockMode - This enum describes the available lock modes. + This enum describes the available lock modes. - \value ReadLock A read lock. - \value WriteLock A write lock. - \value NoLock Neither a read lock nor a write lock. + \value ReadLock A read lock. + \value WriteLock A write lock. + \value NoLock Neither a read lock nor a write lock. */ /*! - Constructs an unlocked \e QtLockedFile object. This constructor - behaves in the same way as \e QFile::QFile(). + Constructs an unlocked \e QtLockedFile object. This constructor + behaves in the same way as \e QFile::QFile(). - \sa QFile::QFile() + \sa QFile::QFile() */ LockedFile::LockedFile() - : QFile() + : QFile() { #ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; + wmutex = 0; + rmutex = 0; #endif - m_lock_mode = NoLock; + m_lock_mode = NoLock; } /*! - Constructs an unlocked QtLockedFile object with file \a name. This - constructor behaves in the same way as \e QFile::QFile(const - QString&). + Constructs an unlocked QtLockedFile object with file \a name. This + constructor behaves in the same way as \e QFile::QFile(const + QString&). - \sa QFile::QFile() + \sa QFile::QFile() */ LockedFile::LockedFile(const QString &name) - : QFile(name) + : QFile(name) { #ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; + wmutex = 0; + rmutex = 0; #endif - m_lock_mode = NoLock; + m_lock_mode = NoLock; } /*! @@ -122,72 +122,72 @@ Returns true if successful; otherwise false. */ bool LockedFile::open(OpenMode mode) { - if (mode & QIODevice::Truncate) { - qWarning("QtLockedFile::open(): Truncate mode not allowed."); - return false; - } - return QFile::open(mode); + if (mode & QIODevice::Truncate) { + qWarning("QtLockedFile::open(): Truncate mode not allowed."); + return false; + } + return QFile::open(mode); } /*! - Returns \e true if this object has a in read or write lock; - otherwise returns \e false. + Returns \e true if this object has a in read or write lock; + otherwise returns \e false. - \sa lockMode() + \sa lockMode() */ bool LockedFile::isLocked() const { - return m_lock_mode != NoLock; + return m_lock_mode != NoLock; } /*! - Returns the type of lock currently held by this object, or \e - QtLockedFile::NoLock. + Returns the type of lock currently held by this object, or \e + QtLockedFile::NoLock. - \sa isLocked() + \sa isLocked() */ LockedFile::LockMode LockedFile::lockMode() const { - return m_lock_mode; + return m_lock_mode; } /*! - \fn bool QtLockedFile::lock(LockMode mode, bool block = true) + \fn bool QtLockedFile::lock(LockMode mode, bool block = true) - Obtains a lock of type \a mode. The file must be opened before it - can be locked. + Obtains a lock of type \a mode. The file must be opened before it + can be locked. - If \a block is true, this function will block until the lock is - aquired. If \a block is false, this function returns \e false - immediately if the lock cannot be aquired. + If \a block is true, this function will block until the lock is + aquired. If \a block is false, this function returns \e false + immediately if the lock cannot be aquired. - If this object already has a lock of type \a mode, this function - returns \e true immediately. If this object has a lock of a - different type than \a mode, the lock is first released and then a - new lock is obtained. + If this object already has a lock of type \a mode, this function + returns \e true immediately. If this object has a lock of a + different type than \a mode, the lock is first released and then a + new lock is obtained. - This function returns \e true if, after it executes, the file is - locked by this object, and \e false otherwise. + This function returns \e true if, after it executes, the file is + locked by this object, and \e false otherwise. - \sa unlock(), isLocked(), lockMode() + \sa unlock(), isLocked(), lockMode() */ /*! - \fn bool QtLockedFile::unlock() + \fn bool QtLockedFile::unlock() - Releases a lock. + Releases a lock. - If the object has no lock, this function returns immediately. + If the object has no lock, this function returns immediately. - This function returns \e true if, after it executes, the file is - not locked by this object, and \e false otherwise. + This function returns \e true if, after it executes, the file is + not locked by this object, and \e false otherwise. - \sa lock(), isLocked(), lockMode() + \sa lock(), isLocked(), lockMode() */ /*! - \fn QtLockedFile::~QtLockedFile() + \fn QtLockedFile::~QtLockedFile() - Destroys the \e QtLockedFile object. If any locks were held, they - are released. + Destroys the \e QtLockedFile object. If any locks were held, they + are released. */ diff --git a/libraries/LocalPeer/src/LockedFile.h b/libraries/LocalPeer/src/LockedFile.h index 8c178250..2f29ee20 100644 --- a/libraries/LocalPeer/src/LockedFile.h +++ b/libraries/LocalPeer/src/LockedFile.h @@ -48,30 +48,30 @@ class LockedFile : public QFile { public: - enum LockMode { NoLock = 0, ReadLock, WriteLock }; + enum LockMode { NoLock = 0, ReadLock, WriteLock }; - LockedFile(); - LockedFile(const QString &name); - ~LockedFile(); + LockedFile(); + LockedFile(const QString &name); + ~LockedFile(); - bool open(OpenMode mode); + bool open(OpenMode mode); - bool lock(LockMode mode, bool block = true); - bool unlock(); - bool isLocked() const; - LockMode lockMode() const; + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; - private: + private: #ifdef Q_OS_WIN - Qt::HANDLE wmutex; - Qt::HANDLE rmutex; - QVector<Qt::HANDLE> rmutexes; - QString mutexname; + Qt::HANDLE wmutex; + Qt::HANDLE rmutex; + QVector<Qt::HANDLE> rmutexes; + QString mutexname; - Qt::HANDLE getMutexHandle(int idx, bool doCreate); - bool waitMutex(Qt::HANDLE mutex, bool doBlock); + Qt::HANDLE getMutexHandle(int idx, bool doCreate); + bool waitMutex(Qt::HANDLE mutex, bool doBlock); #endif - LockMode m_lock_mode; + LockMode m_lock_mode; }; diff --git a/libraries/LocalPeer/src/LockedFile_unix.cpp b/libraries/LocalPeer/src/LockedFile_unix.cpp index 4b68916c..6becc89e 100644 --- a/libraries/LocalPeer/src/LockedFile_unix.cpp +++ b/libraries/LocalPeer/src/LockedFile_unix.cpp @@ -47,68 +47,68 @@ bool LockedFile::lock(LockMode mode, bool block) { - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } - if (mode == NoLock) - return unlock(); + if (mode == NoLock) + return unlock(); - if (mode == m_lock_mode) - return true; + if (mode == m_lock_mode) + return true; - if (m_lock_mode != NoLock) - unlock(); + if (m_lock_mode != NoLock) + unlock(); - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; - int cmd = block ? F_SETLKW : F_SETLK; - int ret = fcntl(handle(), cmd, &fl); + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); - if (ret == -1) { - if (errno != EINTR && errno != EAGAIN) - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } - m_lock_mode = mode; - return true; + m_lock_mode = mode; + return true; } bool LockedFile::unlock() { - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - int ret = fcntl(handle(), F_SETLKW, &fl); - - if (ret == -1) { - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - m_lock_mode = NoLock; - return true; + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_UNLCK; + int ret = fcntl(handle(), F_SETLKW, &fl); + + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + m_lock_mode = NoLock; + return true; } LockedFile::~LockedFile() { - if (isOpen()) - unlock(); + if (isOpen()) + unlock(); } diff --git a/libraries/LocalPeer/src/LockedFile_win.cpp b/libraries/LocalPeer/src/LockedFile_win.cpp index 31238190..93d2c73b 100644 --- a/libraries/LocalPeer/src/LockedFile_win.cpp +++ b/libraries/LocalPeer/src/LockedFile_win.cpp @@ -48,158 +48,158 @@ Qt::HANDLE LockedFile::getMutexHandle(int idx, bool doCreate) { - if (mutexname.isEmpty()) { - QFileInfo fi(*this); - mutexname = QString::fromLatin1(MUTEX_PREFIX) - + fi.absoluteFilePath().toLower(); - } - QString mname(mutexname); - if (idx >= 0) - mname += QString::number(idx); - - Qt::HANDLE mutex; - if (doCreate) { - mutex = CreateMutexW(NULL, FALSE, (LPCWSTR)mname.utf16()); - if (!mutex) { - qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); - return 0; - } - } - else { - mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (LPCWSTR)mname.utf16()); - if (!mutex) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) - qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); - return 0; - } - } - return mutex; + if (mutexname.isEmpty()) { + QFileInfo fi(*this); + mutexname = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + } + QString mname(mutexname); + if (idx >= 0) + mname += QString::number(idx); + + Qt::HANDLE mutex; + if (doCreate) { + mutex = CreateMutexW(NULL, FALSE, (LPCWSTR)mname.utf16()); + if (!mutex) { + qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); + return 0; + } + } + else { + mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (LPCWSTR)mname.utf16()); + if (!mutex) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); + return 0; + } + } + return mutex; } bool LockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) { - Q_ASSERT(mutex); - DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); - switch (res) { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - return true; - break; - case WAIT_TIMEOUT: - break; - default: - qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); - } - return false; + Q_ASSERT(mutex); + DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); + switch (res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return true; + break; + case WAIT_TIMEOUT: + break; + default: + qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); + } + return false; } bool LockedFile::lock(LockMode mode, bool block) { - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - if (!wmutex && !(wmutex = getMutexHandle(-1, true))) - return false; - - if (!waitMutex(wmutex, block)) - return false; - - if (mode == ReadLock) { - int idx = 0; - for (; idx < MAX_READERS; idx++) { - rmutex = getMutexHandle(idx, false); - if (!rmutex || waitMutex(rmutex, false)) - break; - CloseHandle(rmutex); - } - bool ok = true; - if (idx >= MAX_READERS) { - qWarning("QtLockedFile::lock(): too many readers"); - rmutex = 0; - ok = false; - } - else if (!rmutex) { - rmutex = getMutexHandle(idx, true); - if (!rmutex || !waitMutex(rmutex, false)) - ok = false; - } - if (!ok && rmutex) { - CloseHandle(rmutex); - rmutex = 0; - } - ReleaseMutex(wmutex); - if (!ok) - return false; - } - else { - Q_ASSERT(rmutexes.isEmpty()); - for (int i = 0; i < MAX_READERS; i++) { - Qt::HANDLE mutex = getMutexHandle(i, false); - if (mutex) - rmutexes.append(mutex); - } - if (rmutexes.size()) { - DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), - TRUE, block ? INFINITE : 0); - if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { - if (res != WAIT_TIMEOUT) - qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); - m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky - unlock(); - return false; - } - } - } - - m_lock_mode = mode; - return true; + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + if (!wmutex && !(wmutex = getMutexHandle(-1, true))) + return false; + + if (!waitMutex(wmutex, block)) + return false; + + if (mode == ReadLock) { + int idx = 0; + for (; idx < MAX_READERS; idx++) { + rmutex = getMutexHandle(idx, false); + if (!rmutex || waitMutex(rmutex, false)) + break; + CloseHandle(rmutex); + } + bool ok = true; + if (idx >= MAX_READERS) { + qWarning("QtLockedFile::lock(): too many readers"); + rmutex = 0; + ok = false; + } + else if (!rmutex) { + rmutex = getMutexHandle(idx, true); + if (!rmutex || !waitMutex(rmutex, false)) + ok = false; + } + if (!ok && rmutex) { + CloseHandle(rmutex); + rmutex = 0; + } + ReleaseMutex(wmutex); + if (!ok) + return false; + } + else { + Q_ASSERT(rmutexes.isEmpty()); + for (int i = 0; i < MAX_READERS; i++) { + Qt::HANDLE mutex = getMutexHandle(i, false); + if (mutex) + rmutexes.append(mutex); + } + if (rmutexes.size()) { + DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), + TRUE, block ? INFINITE : 0); + if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { + if (res != WAIT_TIMEOUT) + qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); + m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky + unlock(); + return false; + } + } + } + + m_lock_mode = mode; + return true; } bool LockedFile::unlock() { - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - if (m_lock_mode == ReadLock) { - ReleaseMutex(rmutex); - CloseHandle(rmutex); - rmutex = 0; - } - else { - foreach(Qt::HANDLE mutex, rmutexes) { - ReleaseMutex(mutex); - CloseHandle(mutex); - } - rmutexes.clear(); - ReleaseMutex(wmutex); - } - - m_lock_mode = LockedFile::NoLock; - return true; + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + if (m_lock_mode == ReadLock) { + ReleaseMutex(rmutex); + CloseHandle(rmutex); + rmutex = 0; + } + else { + foreach(Qt::HANDLE mutex, rmutexes) { + ReleaseMutex(mutex); + CloseHandle(mutex); + } + rmutexes.clear(); + ReleaseMutex(wmutex); + } + + m_lock_mode = LockedFile::NoLock; + return true; } LockedFile::~LockedFile() { - if (isOpen()) - unlock(); - if (wmutex) - CloseHandle(wmutex); + if (isOpen()) + unlock(); + if (wmutex) + CloseHandle(wmutex); } |