Skip to content

Instantly share code, notes, and snippets.

@cetium
Forked from andrey-str/AppRunGuard.cpp
Created August 10, 2021 08:38
Show Gist options
  • Select an option

  • Save cetium/d6cac199ab438f49049b6ffe81b698d4 to your computer and use it in GitHub Desktop.

Select an option

Save cetium/d6cac199ab438f49049b6ffe81b698d4 to your computer and use it in GitHub Desktop.

Revisions

  1. @andrey-str andrey-str created this gist Sep 11, 2016.
    78 changes: 78 additions & 0 deletions AppRunGuard.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    //
    // Created by Andrey Streltsov on 11/06/15.
    // Based on code from here: http://stackoverflow.com/a/28172162/365754

    #include "AppRunGuard.h"
    #include <qcryptographichash.h>

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

    }


    AppRunGuard::AppRunGuard( const QString& key )
    : key( key )
    , memLockKey( generateKeyHash( key, "_memLockKey" ) )
    , sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) )
    , sharedMem( sharedmemKey )
    , memLock( memLockKey, 1 )
    {
    QSharedMemory fix( sharedmemKey ); // Fix for *nix: http://habrahabr.ru/post/173281/
    fix.attach();
    }

    AppRunGuard::~AppRunGuard()
    {
    release();
    }

    bool AppRunGuard::isAnotherRunning()
    {
    if ( sharedMem.isAttached() )
    return false;

    memLock.acquire();
    const bool isRunning = sharedMem.attach();
    if ( isRunning )
    sharedMem.detach();
    memLock.release();

    return isRunning;
    }

    bool AppRunGuard::tryToRun()
    {
    if ( isAnotherRunning() ) // Extra check
    return false;

    memLock.acquire();
    const bool result = sharedMem.create( sizeof( quint64 ) );
    memLock.release();
    if ( !result )
    {
    release();
    return false;
    }

    return true;
    }

    void AppRunGuard::release()
    {
    memLock.acquire();
    if ( sharedMem.isAttached() )
    sharedMem.detach();
    memLock.release();
    }
    34 changes: 34 additions & 0 deletions AppRunGuard.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    //
    // Created by Andrey Streltsov on 11/06/15.
    // Based on code from here: http://stackoverflow.com/a/28172162/365754

    #ifndef RUNGUARD_H
    #define RUNGUARD_H
    #include <QString>
    #include <qsharedmemory.h>
    #include <qsystemsemaphore.h>


    class AppRunGuard : public QObject {

    public:
    AppRunGuard( const QString& key );
    virtual ~AppRunGuard();

    bool isAnotherRunning();
    bool tryToRun();
    void release();

    private:
    const QString key;
    const QString memLockKey;
    const QString sharedmemKey;

    QSharedMemory sharedMem;
    QSystemSemaphore memLock;

    Q_DISABLE_COPY(AppRunGuard)
    };


    #endif // RUNGUARD_H
    16 changes: 16 additions & 0 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    //
    // Created by Andrey Streltsov on 11/06/15.
    // Usage example

    #define kAppRunUUID "your-app-instance-uuid-here"

    int main(int argc, char *argv[]) {

    AppRunGuard guard(kAppRunUUID);
    if ( !guard.tryToRun() )
    return 1;

    QApplication app(argc, argv);
    return app.exec();

    }