NOISSUE tabs -> spaces

This commit is contained in:
Petr Mrázek
2018-07-15 14:51:05 +02:00
parent 03280cc62e
commit bbb3b3e6f6
577 changed files with 51938 additions and 51938 deletions

View File

@ -12,15 +12,15 @@ include/LocalPeer.h
)
if(UNIX)
list(APPEND SINGLE_SOURCES
src/LockedFile_unix.cpp
)
list(APPEND SINGLE_SOURCES
src/LockedFile_unix.cpp
)
endif()
if(WIN32)
list(APPEND SINGLE_SOURCES
src/LockedFile_win.cpp
)
list(APPEND SINGLE_SOURCES
src/LockedFile_win.cpp
)
endif()
add_library(LocalPeer STATIC ${SINGLE_SOURCES})

View File

@ -50,51 +50,51 @@ class LockedFile;
class ApplicationId
{
public: /* methods */
// traditional app = installed system wide and used in a multi-user environment
static ApplicationId fromTraditionalApp();
// ID based on a path with all the application data (no two instances with the same data path should run)
static ApplicationId fromPathAndVersion(const QString & dataPath, const QString & version);
// custom ID
static ApplicationId fromCustomId(const QString & id);
// custom ID, based on a raw string previously acquired from 'toString'
static ApplicationId fromRawString(const QString & id);
// traditional app = installed system wide and used in a multi-user environment
static ApplicationId fromTraditionalApp();
// ID based on a path with all the application data (no two instances with the same data path should run)
static ApplicationId fromPathAndVersion(const QString & dataPath, const QString & version);
// custom ID
static ApplicationId fromCustomId(const QString & id);
// custom ID, based on a raw string previously acquired from 'toString'
static ApplicationId fromRawString(const QString & id);
QString toString()
{
return m_id;
}
QString toString()
{
return m_id;
}
private: /* methods */
ApplicationId(const QString & value)
{
m_id = value;
}
ApplicationId(const QString & value)
{
m_id = value;
}
private: /* data */
QString m_id;
QString m_id;
};
class LocalPeer : public QObject
{
Q_OBJECT
Q_OBJECT
public:
LocalPeer(QObject *parent, const ApplicationId &appId);
~LocalPeer();
bool isClient();
bool sendMessage(const QString &message, int timeout);
ApplicationId applicationId() const;
LocalPeer(QObject *parent, const ApplicationId &appId);
~LocalPeer();
bool isClient();
bool sendMessage(const QString &message, int timeout);
ApplicationId applicationId() const;
Q_SIGNALS:
void messageReceived(const QString &message);
void messageReceived(const QString &message);
protected Q_SLOTS:
void receiveConnection();
void receiveConnection();
protected:
ApplicationId id;
QString socketName;
std::unique_ptr<QLocalServer> server;
std::unique_ptr<LockedFile> lockFile;
ApplicationId id;
QString socketName;
std::unique_ptr<QLocalServer> server;
std::unique_ptr<LockedFile> lockFile;
};

View File

@ -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;
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;
}
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);
QByteArray uMsg(message.toUtf8());
QDataStream ds(&socket);
ds.writeBytes(uMsg.constData(), uMsg.size());
if(!socket.waitForBytesWritten(timeout))
{
return false;
}
ds.writeBytes(uMsg.constData(), uMsg.size());
if(!socket.waitForBytesWritten(timeout))
{
return false;
}
// wait for 'ack'
if(!socket.waitForReadyRead(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;
// 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;
}
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)
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)
}

View File

@ -41,70 +41,70 @@
#include "LockedFile.h"
/*!
\class QtLockedFile
\class QtLockedFile
\brief The QtLockedFile class extends QFile with advisory locking
functions.
\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.
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 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.
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.
*/

View File

@ -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;
};

View File

@ -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 (!isOpen()) {
qWarning("QtLockedFile::unlock(): file is not opened");
return false;
}
if (!isLocked())
return true;
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);
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;
}
if (ret == -1) {
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
return false;
}
m_lock_mode = NoLock;
return true;
m_lock_mode = NoLock;
return true;
}
LockedFile::~LockedFile()
{
if (isOpen())
unlock();
if (isOpen())
unlock();
}

View File

@ -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);
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;
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 (!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();
if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
return false;
if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
return false;
if (!waitMutex(wmutex, block))
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;
}
}
}
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;
m_lock_mode = mode;
return true;
}
bool LockedFile::unlock()
{
if (!isOpen()) {
qWarning("QtLockedFile::unlock(): file is not opened");
return false;
}
if (!isOpen()) {
qWarning("QtLockedFile::unlock(): file is not opened");
return false;
}
if (!isLocked())
return true;
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);
}
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;
m_lock_mode = LockedFile::NoLock;
return true;
}
LockedFile::~LockedFile()
{
if (isOpen())
unlock();
if (wmutex)
CloseHandle(wmutex);
if (isOpen())
unlock();
if (wmutex)
CloseHandle(wmutex);
}