From cf0d1981cab1fc88b1edb651b11f8b564304e90d Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 14 Sep 2015 14:53:49 +0300 Subject: [PATCH] Moved lock-guarding abilities to separated template class. Changed application/mainwindow to use it. Most likelly mainwindow may be upgraded more, since lock can hold and manage memory for complex object like QFile, also it can have stored deallocator for the object (lambdas), so this is effectively should simple code, when you have allocation and freening resources declared on the same screen. --HG-- branch : develop --- src/app/tape/tmainwindow.cpp | 40 ++--- src/app/tape/tmainwindow.h | 9 +- src/app/valentina/core/vapplication.cpp | 113 +++++-------- src/app/valentina/core/vapplication.h | 9 +- src/app/valentina/mainwindow.cpp | 33 +--- src/app/valentina/mainwindow.h | 9 +- src/libs/vmisc/vabstractapplication.cpp | 44 ------ src/libs/vmisc/vabstractapplication.h | 8 +- src/libs/vmisc/vlockguard.h | 200 ++++++++++++++++++++++++ src/libs/vmisc/vmisc.pri | 3 +- 10 files changed, 268 insertions(+), 200 deletions(-) create mode 100644 src/libs/vmisc/vlockguard.h diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index e8a8331e3..8f433f598 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -37,6 +37,7 @@ #include "../ifc/xml/vvitconverter.h" #include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vpatternconverter.h" +#include "../vmisc/vlockguard.h" #include "vlitepattern.h" #include "../qmuparser/qmudef.h" #include "../vtools/dialogs/support/dialogeditwrongformula.h" @@ -48,9 +49,6 @@ #include #include #include -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -# include -#endif #define DIALOG_MAX_FORMULA_HEIGHT 64 @@ -98,10 +96,6 @@ TMainWindow::~TMainWindow() delete m; } -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - delete lock; // Unlock pattern file -#endif - delete ui; } @@ -182,18 +176,13 @@ void TMainWindow::LoadFile(const QString &path) } } -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - lock = new QLockFile(QFileInfo(path).fileName()+".lock"); - lock->setStaleLockTime(0); - if (not MApplication::TryLock(lock)) + VlpCreateLock(lock, QFileInfo(path).fileName()+".lock"); + + if (lock->GetLockError() == QLockFile::LockFailedError) { - if (lock->error() == QLockFile::LockFailedError) - { - qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); - return; - } + qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); + return; } -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) try { @@ -839,18 +828,13 @@ void TMainWindow::ImportFromPattern() return; } -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - QLockFile *lock = new QLockFile(QFileInfo(mPath).fileName()+".lock"); - lock->setStaleLockTime(0); - if (not MApplication::TryLock(lock)) + VLockGuard tmp(QFileInfo(mPath).fileName()+".lock"); + + if (tmp.GetLockError() == QLockFile::LockFailedError) { - if (lock->error() == QLockFile::LockFailedError) - { - qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); - return; - } + qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); + return; } -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) #ifdef Q_OS_WIN32 qt_ntfs_permission_lookup++; // turn checking on @@ -878,8 +862,6 @@ void TMainWindow::ImportFromPattern() qt_ntfs_permission_lookup--; // turn it off again #endif /*Q_OS_WIN32*/ - delete lock; // release a pattern file - measurements = FilterMeasurements(measurements, m->ListAll()); qint32 currentRow; diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h index 889505403..816c590dd 100644 --- a/src/app/tape/tmainwindow.h +++ b/src/app/tape/tmainwindow.h @@ -33,6 +33,7 @@ #include #include "../vmisc/def.h" +#include "../vmisc/vlockguard.h" #include "../vformat/vmeasurements.h" namespace Ui @@ -43,9 +44,6 @@ namespace Ui class QComboBox; class QTableWidgetItem; class QLabel; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -class QLockFile; -#endif class TMainWindow : public QMainWindow { @@ -133,10 +131,7 @@ private: QComboBox *gradationSizes; QComboBox *comboBoxUnits; int formulaBaseHeight; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - QLockFile *lock; -#endif + VLockGuardPtr lock; void SetupMenu(); void InitWindow(); diff --git a/src/app/valentina/core/vapplication.cpp b/src/app/valentina/core/vapplication.cpp index 549a73cc2..fed2815d8 100644 --- a/src/app/valentina/core/vapplication.cpp +++ b/src/app/valentina/core/vapplication.cpp @@ -53,6 +53,8 @@ Q_LOGGING_CATEGORY(vApp, "v.application") +constexpr auto DAYS_TO_KEEP_LOGS = 3; + //--------------------------------------------------------------------------------------------------------------------- inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { @@ -170,12 +172,8 @@ const QString VApplication::GistFileName = QStringLiteral("gist.json"); VApplication::VApplication(int &argc, char **argv) : VAbstractApplication(argc, argv), trVars(nullptr), autoSaveTimer(nullptr), - log(nullptr), - #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - out(nullptr), logLock(nullptr) - #else + lockLog(), out(nullptr) - #endif { VCommandLine::Reset(); // making sure will create new instance...just in case we will ever do 2 objects of VApplication VCommandLine::Get(*this); @@ -187,16 +185,6 @@ VApplication::~VApplication() { qCDebug(vApp, "Application closing."); qInstallMessageHandler(0); // Resore the message handler - delete out; - - if (log != nullptr) - { - log->close(); - delete log; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - delete logLock; -#endif - } delete trVars; VCommandLine::Reset(); } @@ -418,32 +406,25 @@ void VApplication::CreateLogDir() const //--------------------------------------------------------------------------------------------------------------------- void VApplication::BeginLogging() { - log = new QFile(LogPath()); - if (log->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) - { - out = new QTextStream(log); - qInstallMessageHandler(noisyFailureMsgHandler); + VlpCreateLock(lockLog, LogPath()+".lock", [this](){return new QFile(LogPath());}); -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - logLock = new QLockFile(LogPath()+".lock"); - logLock->setStaleLockTime(0); - if (TryLock(logLock)) + if (lockLog->IsLocked()) + { + if (lockLog->GetProtected()->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { + out.reset(new QTextStream(lockLog->GetProtected().get())); + qInstallMessageHandler(noisyFailureMsgHandler); qCDebug(vApp, "Log file %s was locked.", LogPath().toUtf8().constData()); } else { - qCDebug(vApp, "Failed to lock %s", LogPath().toUtf8().constData()); - qCDebug(vApp, "Error type: %d", logLock->error()); + qCDebug(vApp, "Error opening log file \'%s\'. All debug output redirected to console.", + LogPath().toUtf8().constData()); } -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) } else { - delete log; - log = nullptr; - qCDebug(vApp, "Error opening log file \'%s\'. All debug output redirected to console.", - LogPath().toUtf8().constData()); + qCDebug(vApp, "Failed to lock %s", LogPath().toUtf8().constData()); } } @@ -459,45 +440,29 @@ void VApplication::ClearOldLogs() const if (allFiles.isEmpty() == false) { qCDebug(vApp, "Clearing old logs"); - for (int i = 0; i < allFiles.size(); ++i) + for (int i = 0, sz = allFiles.size(); i < sz; ++i) { - QFileInfo info(allFiles.at(i)); -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - QLockFile *lock = new QLockFile(info.absoluteFilePath() + ".lock"); - if (TryLock(lock)) + auto fn = allFiles.at(i); + QFileInfo info(fn); + if (info.created().daysTo(QDateTime::currentDateTime()) >= DAYS_TO_KEEP_LOGS) { - qCDebug(vApp, "Locked file %s", info.absoluteFilePath().toUtf8().constData()); - QFile oldLog(allFiles.at(i)); - if (oldLog.remove()) + VLockGuard tmp(info.absoluteFilePath() + ".lock", [&fn](){return new QFile(fn);}); + if (tmp.GetProtected() != nullptr) { - qCDebug(vApp, "Deleted %s", info.absoluteFilePath().toUtf8().constData()); + if (tmp.GetProtected()->remove()) + { + qCDebug(vApp, "Deleted %s", info.absoluteFilePath().toUtf8().constData()); + } + else + { + qCDebug(vApp, "Could not delete %s", info.absoluteFilePath().toUtf8().constData()); + } } else { - qCDebug(vApp, "Could not delete %s", info.absoluteFilePath().toUtf8().constData()); + qCDebug(vApp, "Failed to lock %s", info.absoluteFilePath().toUtf8().constData()); } } - else - { - qCDebug(vApp, "Failed to lock %s", info.absoluteFilePath().toUtf8().constData()); - } - - delete lock; - lock = nullptr; -#else - if (info.created().daysTo(QDateTime::currentDateTime()) >= 3) - { - QFile oldLog(allFiles.at(i)); - if (oldLog.remove()) - { - qCDebug(vApp, "Deleted %s", info.absoluteFilePath().toUtf8().constData()); - } - else - { - qCDebug(vApp, "Could not delete %s", info.absoluteFilePath().toUtf8().constData()); - } - } -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) } } else @@ -614,7 +579,7 @@ void VApplication::StartLogging() //--------------------------------------------------------------------------------------------------------------------- QTextStream *VApplication::LogFile() { - return out; + return out.get(); } //--------------------------------------------------------------------------------------------------------------------- @@ -707,27 +672,28 @@ void VApplication::GatherLogs() const const QStringList allFiles = logsDir.entryList(QDir::NoDotAndDotDot | QDir::Files); if (allFiles.isEmpty() == false) { - for (int i = 0; i < allFiles.size(); ++i) + for (int i = 0, sz = allFiles.size(); i < sz; ++i) { - QFileInfo info(allFiles.at(i)); + auto fn = allFiles.at(i); + QFileInfo info(fn); if (info.fileName() == "valentina.log") { continue; } - QLockFile *logLock = new QLockFile(info.absoluteFilePath()+".lock"); - logLock->setStaleLockTime(0); - if (TryLock(logLock)) + + VLockGuard tmp(info.absoluteFilePath() + ".lock", [&fn](){return new QFile(fn);}); + + if (tmp.IsLocked()) { *out <<"--------------------------" << endl; - QFile logFile(info.absoluteFilePath()); - if (logFile.open(QIODevice::ReadOnly | QIODevice::Text)) + if (tmp.GetProtected()->open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream in(&logFile); + QTextStream in(&tmp.GetProtected()); while (!in.atEnd()) { *out << in.readLine() << endl; } - logFile.close(); + tmp.GetProtected()->close(); } else { @@ -736,9 +702,8 @@ void VApplication::GatherLogs() const } else { - *out << "Could not lock" << info.absoluteFilePath() << "."; + qCDebug(vApp, "Failed to lock %s", info.absoluteFilePath().toUtf8().constData()); } - delete logLock; } } else diff --git a/src/app/valentina/core/vapplication.h b/src/app/valentina/core/vapplication.h index 8d522e6d3..28e24e84d 100644 --- a/src/app/valentina/core/vapplication.h +++ b/src/app/valentina/core/vapplication.h @@ -36,7 +36,6 @@ #include "vsettings.h" #include "vcmdexport.h" - class VApplication;// use in define class VMainGraphicsView; class VPattern; @@ -95,11 +94,9 @@ private: VTranslateVars *trVars; QTimer *autoSaveTimer; - QFile *log; - QTextStream *out; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - QLockFile *logLock; -#endif + VLockGuardPtr lockLog; + std::shared_ptr out; + void InitLineWidth(); #if defined(Q_OS_WIN) && defined(Q_CC_GNU) diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index dd18cec5e..5610c83cb 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -62,9 +62,6 @@ #include #include #include -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -# include -#endif #include #include @@ -1960,13 +1957,8 @@ void MainWindow::OnlineHelp() void MainWindow::Clear() { qCDebug(vMainWindow, "Reseting main window."); - -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - delete lock; // Unlock pattern file - lock = nullptr; + lock.reset(); qCDebug(vMainWindow, "Unlocked pattern file."); -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - ui->actionDetails->setChecked(true); ui->actionDraw->setChecked(true); ui->actionLayout->setEnabled(true); @@ -3034,9 +3026,6 @@ MainWindow::~MainWindow() CancelTool(); CleanLayout(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - delete lock; // Unlock pattern file -#endif delete doc; delete sceneDetails; delete sceneDraw; @@ -3065,26 +3054,24 @@ bool MainWindow::LoadPattern(const QString &fileName, const QString& customMeasu return false; } -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) qCDebug(vMainWindow, "Loking file"); - lock = new QLockFile(fileName+".lock"); - lock->setStaleLockTime(0); - if (VApplication::TryLock(lock)) + VlpCreateLock(lock, fileName+".lock"); + + if (lock->IsLocked()) { qCDebug(vMainWindow, "Pattern file %s was locked.", fileName.toUtf8().constData()); } else { qCDebug(vMainWindow, "Failed to lock %s", fileName.toUtf8().constData()); - qCDebug(vMainWindow, "Error type: %d", lock->error()); - if (lock->error() == QLockFile::LockFailedError) + qCDebug(vMainWindow, "Error type: %d", lock->GetLockError()); + if (lock->GetLockError() == QLockFile::LockFailedError) { qCCritical(vMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); Clear(); return false; } } -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) // On this stage scene empty. Fit scene size to view size VMainGraphicsView::NewSceneRect(sceneDraw, ui->view); @@ -3187,14 +3174,11 @@ QStringList MainWindow::GetUnlokedRestoreFileList() const for (int i = 0; i < files.size(); ++i) { // Seeking file that realy need reopen - QLockFile *lock = new QLockFile(files.at(i)+".lock"); - lock->setStaleLockTime(0); - if (VApplication::TryLock(lock)) + VLockGuard tmp(files.at(i)+".lock"); + if (tmp.IsLocked()) { restoreFiles.append(files.at(i)); } - delete lock; - lock = nullptr; } // Clearing list after filtering @@ -3204,7 +3188,6 @@ QStringList MainWindow::GetUnlokedRestoreFileList() const } qApp->ValentinaSettings()->SetRestoreFileList(files); - } return restoreFiles; #else diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h index d934cfa93..d2c29555c 100644 --- a/src/app/valentina/mainwindow.h +++ b/src/app/valentina/mainwindow.h @@ -37,7 +37,7 @@ #include "tools/vtooluniondetails.h" #include "tools/drawTools/drawtools.h" #include "core/vcmdexport.h" -#include +#include "../vmisc/vlockguard.h" #include @@ -47,9 +47,6 @@ namespace Ui } class VToolOptionsPropertyBrowser; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -class QLockFile; -#endif /** * @brief The MainWindow class main windows. @@ -230,9 +227,7 @@ private: QComboBox *gradationHeights; QComboBox *gradationSizes; VToolOptionsPropertyBrowser *toolOptions; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - QLockFile *lock; -#endif + VLockGuardPtr lock; void ToolBarOption(); void ToolBarStages(); diff --git a/src/libs/vmisc/vabstractapplication.cpp b/src/libs/vmisc/vabstractapplication.cpp index 26d612620..d687acd66 100644 --- a/src/libs/vmisc/vabstractapplication.cpp +++ b/src/libs/vmisc/vabstractapplication.cpp @@ -29,10 +29,6 @@ #include "vabstractapplication.h" #include "../vmisc/def.h" -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -# include -#endif - //--------------------------------------------------------------------------------------------------------------------- VAbstractApplication::VAbstractApplication(int &argc, char **argv) :QApplication(argc, argv), @@ -116,43 +112,3 @@ double VAbstractApplication::fromPixel(double pix) const { return FromPixel(pix, _patternUnit); } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -//--------------------------------------------------------------------------------------------------------------------- -bool VAbstractApplication::TryLock(QLockFile *lock) -{ - if (lock == nullptr) - { - return false; - } - - if (lock->tryLock()) - { - return true; - } - else - { - if (lock->error() == QLockFile::LockFailedError) - { - // This happens if a stale lock file exists and another process uses that PID. - // Try removing the stale file, which will fail if a real process is holding a - // file-level lock. A false error is more problematic than not locking properly - // on corner-case systems. - if (lock->removeStaleLockFile() == false || lock->tryLock() == false) - { - return false; - } - else - { - return true; - } - } - else - { - return false; - } - return false; - } -} - -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) diff --git a/src/libs/vmisc/vabstractapplication.h b/src/libs/vmisc/vabstractapplication.h index d8c7fec6e..2c687f7ee 100644 --- a/src/libs/vmisc/vabstractapplication.h +++ b/src/libs/vmisc/vabstractapplication.h @@ -33,15 +33,13 @@ #include #include "def.h" #include "vsettings.h" +#include "vlockguard.h" class VAbstractApplication;// use in define class VTranslateVars; class VAbstractPattern; class VMainGraphicsView; class QUndoStack; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) -class QLockFile; -#endif #if defined(qApp) #undef qApp @@ -89,10 +87,6 @@ public: QUndoStack *getUndoStack() const; -#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - static bool TryLock(QLockFile *lock); -#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) - protected: QUndoStack *undoStack; diff --git a/src/libs/vmisc/vlockguard.h b/src/libs/vmisc/vlockguard.h new file mode 100644 index 000000000..395a1a265 --- /dev/null +++ b/src/libs/vmisc/vlockguard.h @@ -0,0 +1,200 @@ +/************************************************************************ + ** + ** @file VLockGuard.h + ** @author Alex Zaharov + ** @author Roman Telezhynskyi + ** @date 14 9, 2015 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#ifndef VLOCKGUARD_H +#define VLOCKGUARD_H + +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) +#include +#define PEDANT_COMPILER ,lock(nullptr) +#else +#define PEDANT_COMPILER +#warning To have lock-file support you must use Qt 5.1+. Expect collissions when run 2 copies of the program. +#endif + +/*@brief + * This class creates Guarded object if and only if lock file taken. It keeps shared_ptr to object and lock-file. + * Can use optional object allocator and deleter. + * + * On older Qt lock assumed always taken and compile-time warning is shown. + * +*/ +template +class VLockGuard +{ +public: + VLockGuard(const QString& lockName, int stale = 0, int timeout = 0); + + template + VLockGuard(const QString& lockName, Alloc a, int stale = 0, int timeout=0); + + template + VLockGuard(const QString& lockName, Alloc a, Delete d, int stale = 0, int timeout=0); + + const std::shared_ptr &GetProtected() const; + int GetLockError() const; + bool IsLocked() const; + +private: + Q_DISABLE_COPY(VLockGuard) + + std::shared_ptr holder; + int lockError; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) + std::shared_ptr lock; +#endif + + bool TryLock(const QString &lockName, int stale, int timeout); +}; + +//--------------------------------------------------------------------------------------------------------------------- +template +VLockGuard::VLockGuard(const QString &lockName, int stale, int timeout) + : holder(nullptr), lockError(0) PEDANT_COMPILER +{ + if (TryLock(lockName, stale, timeout)) + { + holder.reset(new Guarded()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +//using allocator lambdas seems logically better than supplying pointer, because we will take ownership of allocated +//object +template template +VLockGuard::VLockGuard(const QString& lockName, Alloc a, int stale, int timeout) + : holder(nullptr), lockError(0) PEDANT_COMPILER +{ + if (TryLock(lockName, stale, timeout)) + { + holder.reset(a()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +template template +VLockGuard::VLockGuard(const QString& lockName, Alloc a, Delete d, int stale, int timeout) + : holder(nullptr), lockError(0) PEDANT_COMPILER +{ + if (TryLock(lockName, stale, timeout)) + { + holder.reset(a(), d); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +template +const std::shared_ptr &VLockGuard::GetProtected() const +{ + return holder; +} + +//--------------------------------------------------------------------------------------------------------------------- +template +int VLockGuard::GetLockError() const +{ + return lockError; +} + +//--------------------------------------------------------------------------------------------------------------------- +template +bool VLockGuard::IsLocked() const +{ + return holder != nullptr; +} + +//--------------------------------------------------------------------------------------------------------------------- +template +bool VLockGuard::TryLock(const QString &lockName, int stale, int timeout) +{ + bool res = true; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) + + lock.reset(new QLockFile(lockName)); + lock->setStaleLockTime(stale); + + for (int i = 0; i < 2 && !lock->tryLock(timeout); i++) + { + if (QLockFile::LockFailedError != lock->error()) + { + break; + } + else + { + // This happens if a stale lock file exists and another process uses that PID. + // Try removing the stale file, which will fail if a real process is holding a + // file-level lock. A false error is more problematic than not locking properly + // on corner-case systems. + lock->removeStaleLockFile(); + lock->tryLock(timeout); + } + } + res = QLockFile::NoError == (lockError = lock->error()); + if (!res) + { + lock.reset(); + } +#endif + return res; +} + +#undef PEDANT_COMPILER + +//use pointer and function below to persistent things like class-member, because lock is taken by constructor +//helper functions allow to write shorter creating and setting new lock-pointer + +//new C++11 - "template typedef" http://stackoverflow.com/questions/2795023/c-template-typedef +template +using VLockGuardPtr = std::shared_ptr>; + +template +void VlpCreateLock(VLockGuardPtr& r, const QString& lockName, int stale = 0, int timeout = 0) +{ + r.reset(new VLockGuard(lockName, stale, timeout)); +} + +template +void VlpCreateLock(VLockGuardPtr& r, const QString& lockName, Alloc a, int stale = 0, int timeout = 0) +{ + r.reset(new VLockGuard(lockName, a, stale, timeout)); +} + +template +void VlpCreateLock(VLockGuardPtr& r, const QString& lockName, Alloc a, Del d, int stale = 0, int timeout = 0) +{ + r.reset(new VLockGuard(lockName, a, d, stale, timeout)); +} + +#endif // VLOCKGUARD_H diff --git a/src/libs/vmisc/vmisc.pri b/src/libs/vmisc/vmisc.pri index 3f7187d56..775357374 100644 --- a/src/libs/vmisc/vmisc.pri +++ b/src/libs/vmisc/vmisc.pri @@ -26,4 +26,5 @@ HEADERS += \ $$PWD/projectversion.h \ $$PWD/vcommonsettings.h \ $$PWD/vtapesettings.h \ - debugbreak.h + $$PWD/debugbreak.h \ + $$PWD/vlockguard.h