forked from mirror/nheko
parent
7de5af83db
commit
65672d3dfb
@ -0,0 +1,31 @@ |
||||
#pragma once |
||||
|
||||
//
|
||||
// Taken from
|
||||
// https://stackoverflow.com/questions/5006547/qt-best-practice-for-a-single-instance-app-protection
|
||||
//
|
||||
|
||||
#include <QObject> |
||||
#include <QSharedMemory> |
||||
#include <QSystemSemaphore> |
||||
|
||||
class RunGuard |
||||
{ |
||||
public: |
||||
RunGuard(const QString &key); |
||||
~RunGuard(); |
||||
|
||||
bool isAnotherRunning(); |
||||
bool tryToRun(); |
||||
void release(); |
||||
|
||||
private: |
||||
const QString key; |
||||
const QString memLockKey; |
||||
const QString sharedmemKey; |
||||
|
||||
QSharedMemory sharedMem; |
||||
QSystemSemaphore memLock; |
||||
|
||||
Q_DISABLE_COPY(RunGuard) |
||||
}; |
@ -0,0 +1,84 @@ |
||||
#include "RunGuard.h" |
||||
|
||||
#include <QCryptographicHash> |
||||
|
||||
namespace { |
||||
|
||||
QString |
||||
generateKeyHash(const QString &key, const QString &salt) |
||||
{ |
||||
QByteArray data; |
||||
|
||||
data.append(key.toUtf8()); |
||||
data.append(salt.toUtf8()); |
||||
data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex(); |
||||
|
||||
return data; |
||||
} |
||||
} |
||||
|
||||
RunGuard::RunGuard(const QString &key) |
||||
: key(key) |
||||
, memLockKey(generateKeyHash(key, "_memLockKey")) |
||||
, sharedmemKey(generateKeyHash(key, "_sharedmemKey")) |
||||
, sharedMem(sharedmemKey) |
||||
, memLock(memLockKey, 1) |
||||
{ |
||||
memLock.acquire(); |
||||
{ |
||||
// Fix for *nix: http://habrahabr.ru/post/173281/
|
||||
QSharedMemory fix(sharedmemKey); |
||||
fix.attach(); |
||||
} |
||||
|
||||
memLock.release(); |
||||
} |
||||
|
||||
RunGuard::~RunGuard() { release(); } |
||||
|
||||
bool |
||||
RunGuard::isAnotherRunning() |
||||
{ |
||||
if (sharedMem.isAttached()) |
||||
return false; |
||||
|
||||
memLock.acquire(); |
||||
const bool isRunning = sharedMem.attach(); |
||||
|
||||
if (isRunning) |
||||
sharedMem.detach(); |
||||
|
||||
memLock.release(); |
||||
|
||||
return isRunning; |
||||
} |
||||
|
||||
bool |
||||
RunGuard::tryToRun() |
||||
{ |
||||
// Extra check
|
||||
if (isAnotherRunning()) |
||||
return false; |
||||
|
||||
memLock.acquire(); |
||||
const bool result = sharedMem.create(sizeof(quint64)); |
||||
memLock.release(); |
||||
|
||||
if (!result) { |
||||
release(); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
void |
||||
RunGuard::release() |
||||
{ |
||||
memLock.acquire(); |
||||
|
||||
if (sharedMem.isAttached()) |
||||
sharedMem.detach(); |
||||
|
||||
memLock.release(); |
||||
} |
Loading…
Reference in new issue