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
This commit is contained in:
parent
1e806ccc08
commit
cf0d1981ca
|
@ -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 <QMessageBox>
|
||||
#include <QComboBox>
|
||||
#include <QProcess>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||
# include <QLockFile>
|
||||
#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<char> 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;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <QTableWidget>
|
||||
|
||||
#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<char> lock;
|
||||
|
||||
void SetupMenu();
|
||||
void InitWindow();
|
||||
|
|
|
@ -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<QFile> 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<QFile> 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
|
||||
|
|
|
@ -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<QFile> lockLog;
|
||||
std::shared_ptr<QTextStream> out;
|
||||
|
||||
void InitLineWidth();
|
||||
|
||||
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||
|
|
|
@ -62,9 +62,6 @@
|
|||
#include <QtGlobal>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDesktopServices>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||
# include <QLockFile>
|
||||
#endif
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
@ -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<char> 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
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "tools/vtooluniondetails.h"
|
||||
#include "tools/drawTools/drawtools.h"
|
||||
#include "core/vcmdexport.h"
|
||||
#include <QLockFile>
|
||||
#include "../vmisc/vlockguard.h"
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
|
@ -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<char> lock;
|
||||
|
||||
void ToolBarOption();
|
||||
void ToolBarStages();
|
||||
|
|
|
@ -29,10 +29,6 @@
|
|||
#include "vabstractapplication.h"
|
||||
#include "../vmisc/def.h"
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||
# include <QLockFile>
|
||||
#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)
|
||||
|
|
|
@ -33,15 +33,13 @@
|
|||
#include <QGraphicsScene>
|
||||
#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;
|
||||
|
||||
|
|
200
src/libs/vmisc/vlockguard.h
Normal file
200
src/libs/vmisc/vlockguard.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file VLockGuard.h
|
||||
** @author Alex Zaharov <alexzkhr@gmail.com>
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @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
|
||||
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef VLOCKGUARD_H
|
||||
#define VLOCKGUARD_H
|
||||
|
||||
#include <QString>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||
#include <QLockFile>
|
||||
#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 <typename Guarded>
|
||||
class VLockGuard
|
||||
{
|
||||
public:
|
||||
VLockGuard(const QString& lockName, int stale = 0, int timeout = 0);
|
||||
|
||||
template <typename Alloc>
|
||||
VLockGuard(const QString& lockName, Alloc a, int stale = 0, int timeout=0);
|
||||
|
||||
template <typename Alloc, typename Delete>
|
||||
VLockGuard(const QString& lockName, Alloc a, Delete d, int stale = 0, int timeout=0);
|
||||
|
||||
const std::shared_ptr<Guarded> &GetProtected() const;
|
||||
int GetLockError() const;
|
||||
bool IsLocked() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(VLockGuard<Guarded>)
|
||||
|
||||
std::shared_ptr<Guarded> holder;
|
||||
int lockError;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||
std::shared_ptr<QLockFile> lock;
|
||||
#endif
|
||||
|
||||
bool TryLock(const QString &lockName, int stale, int timeout);
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
template <typename Guarded>
|
||||
VLockGuard<Guarded>::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 <typename Guarded> template <typename Alloc>
|
||||
VLockGuard<Guarded>::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 <typename Guarded> template <typename Alloc, typename Delete>
|
||||
VLockGuard<Guarded>::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 <typename Guarded>
|
||||
const std::shared_ptr<Guarded> &VLockGuard<Guarded>::GetProtected() const
|
||||
{
|
||||
return holder;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
template <typename Guarded>
|
||||
int VLockGuard<Guarded>::GetLockError() const
|
||||
{
|
||||
return lockError;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
template <typename Guarded>
|
||||
bool VLockGuard<Guarded>::IsLocked() const
|
||||
{
|
||||
return holder != nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
template <typename Guarded>
|
||||
bool VLockGuard<Guarded>::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 <typename Guarded>
|
||||
using VLockGuardPtr = std::shared_ptr<VLockGuard<Guarded>>;
|
||||
|
||||
template <typename Guarded>
|
||||
void VlpCreateLock(VLockGuardPtr<Guarded>& r, const QString& lockName, int stale = 0, int timeout = 0)
|
||||
{
|
||||
r.reset(new VLockGuard<Guarded>(lockName, stale, timeout));
|
||||
}
|
||||
|
||||
template <typename Guarded, typename Alloc>
|
||||
void VlpCreateLock(VLockGuardPtr<Guarded>& r, const QString& lockName, Alloc a, int stale = 0, int timeout = 0)
|
||||
{
|
||||
r.reset(new VLockGuard<Guarded>(lockName, a, stale, timeout));
|
||||
}
|
||||
|
||||
template <typename Guarded, typename Alloc, typename Del>
|
||||
void VlpCreateLock(VLockGuardPtr<Guarded>& r, const QString& lockName, Alloc a, Del d, int stale = 0, int timeout = 0)
|
||||
{
|
||||
r.reset(new VLockGuard<Guarded>(lockName, a, d, stale, timeout));
|
||||
}
|
||||
|
||||
#endif // VLOCKGUARD_H
|
|
@ -26,4 +26,5 @@ HEADERS += \
|
|||
$$PWD/projectversion.h \
|
||||
$$PWD/vcommonsettings.h \
|
||||
$$PWD/vtapesettings.h \
|
||||
debugbreak.h
|
||||
$$PWD/debugbreak.h \
|
||||
$$PWD/vlockguard.h
|
||||
|
|
Loading…
Reference in New Issue
Block a user