support single instance app

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-11-22 21:40:51 +08:00
parent 3722e6cb71
commit 50db1a63ba
4 changed files with 116 additions and 2 deletions

View File

@ -3,9 +3,15 @@
#include <QFile>
#include <QTextCodec>
#include "utils/vutils.h"
#include "vsingleinstanceguard.h"
int main(int argc, char *argv[])
{
VSingleInstanceGuard guard;
if (!guard.tryRun()) {
return 0;
}
QApplication app(argc, argv);
QTextCodec *codec = QTextCodec::codecForName("UTF8");

View File

@ -43,7 +43,8 @@ SOURCES += main.cpp\
vedittab.cpp \
voutline.cpp \
vtoc.cpp \
vfilelocation.cpp
vfilelocation.cpp \
vsingleinstanceguard.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@ -75,7 +76,8 @@ HEADERS += vmainwindow.h \
vedittab.h \
voutline.h \
vtoc.h \
vfilelocation.h
vfilelocation.h \
vsingleinstanceguard.h
RESOURCES += \
vnote.qrc

View File

@ -0,0 +1,73 @@
#include "vsingleinstanceguard.h"
#include <QDebug>
const QString VSingleInstanceGuard::m_memKey = "vnote_shared_memory";
const QString VSingleInstanceGuard::m_semKey = "vnote_semaphore";
const int VSingleInstanceGuard::m_magic = 133191933;
VSingleInstanceGuard::VSingleInstanceGuard()
: m_sharedMemory(m_memKey), m_sem(m_semKey, 1)
{
}
VSingleInstanceGuard::~VSingleInstanceGuard()
{
if (m_sharedMemory.isAttached()) {
detachMemory();
}
}
void VSingleInstanceGuard::detachMemory()
{
m_sem.acquire();
m_sharedMemory.detach();
m_sem.release();
}
bool VSingleInstanceGuard::tryAttach()
{
m_sem.acquire();
bool ret = m_sharedMemory.attach();
m_sem.release();
if (ret) {
m_sharedMemory.lock();
SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
str->m_activeRequest = 1;
m_sharedMemory.unlock();
detachMemory();
}
return ret;
}
bool VSingleInstanceGuard::tryRun()
{
// If we can attach to the sharedmemory, there is another instance running.
if (tryAttach()) {
qDebug() << "Another instance is running";
return false;
}
// Try to create it
m_sem.acquire();
bool ret = m_sharedMemory.create(sizeof(SharedStruct));
m_sem.release();
if (ret) {
// We created it
m_sharedMemory.lock();
SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
str->m_magic = m_magic;
str->m_activeRequest = 0;
m_sharedMemory.unlock();
return true;
} else {
// Maybe another thread create it
if (tryAttach()) {
qDebug() << "Another instance is running";
return false;
} else {
// Something wrong here
qWarning() << "error: failed to create or attach shared memory segment";
return false;
}
}
}

View File

@ -0,0 +1,33 @@
#ifndef VSINGLEINSTANCEGUARD_H
#define VSINGLEINSTANCEGUARD_H
#include <QString>
#include <QSharedMemory>
#include <QSystemSemaphore>
class VSingleInstanceGuard
{
public:
VSingleInstanceGuard();
~VSingleInstanceGuard();
bool tryRun();
private:
void detachMemory();
bool tryAttach();
struct SharedStruct {
// A magic number to identify if this struct is initialized
int m_magic;
// If it is 1, then another instance ask this instance to show itself
int m_activeRequest;
};
static const QString m_memKey;
static const QString m_semKey;
static const int m_magic;
QSharedMemory m_sharedMemory;
QSystemSemaphore m_sem;
};
#endif // VSINGLEINSTANCEGUARD_H