Skip to content
Snippets Groups Projects
RunGuard.cc 1.81 KiB
Newer Older
  • Learn to ignore specific revisions
  • /****************************************************************************
     *
     *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
     *
     * QGroundControl is licensed according to the terms in the file
     * COPYING.md in the root of the source code directory.
     *
     ****************************************************************************/
    
    #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();
        {
            QSharedMemory fix( sharedmemKey );    // Fix for *nix: http://habrahabr.ru/post/173281/
            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()
    {
        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 RunGuard::release()
    {
        memLock.acquire();
        if ( sharedMem.isAttached() )
            sharedMem.detach();
        memLock.release();
    }