Just Intonation  Version 1.3.1 (19)
Explore key-independent dynamically adapting tuning in just intonation
runguard.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright 2016-2017 Karolin Stange, Christoph Wick, and Haye Hinrichsen
3  *
4  * This file is part of JustIntonation.
5  *
6  * JustIntonation is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * JustIntonation is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with JustIntonation. If not, see http://www.gnu.org/licenses/.
18  *****************************************************************************/
19 
20 //============================================================================
21 // RunGuard, preventing multiple instances of the application
22 //============================================================================
23 
24 // The code is based on the RunGuard used in the Entropy Piao Tuner
25 // developed by Christoph Wick
26 
27 #include "runguard.h"
28 #include "shared.h"
29 
30 #include <QCryptographicHash>
31 #include <QMessageBox>
32 
33 #include <iostream>
34 
35 //-----------------------------------------------------------------------------
36 // Constructor
37 //-----------------------------------------------------------------------------
38 
47 
48 RunGuard::RunGuard (const QString& key)
49  : mKey (key)
50  , mMemLockKey (generateKeyHash( key, "_memLockKey" ))
51  , mSharedMemKey (generateKeyHash( key, "_sharedmemKey"))
52  , mSharedMem (mSharedMemKey)
53  , mMemLock (mMemLockKey, 1)
54 {
55  // Fix, see http://habrahabr.ru/post/173281/
56  {
57  QSharedMemory fix (mSharedMemKey);
58  fix.attach();
59  }
60 
61  mMemLock.acquire();
62  const bool success = mSharedMem.create( sizeof( quint64 ) );
63  mMemLock.release();
64  if (not success) release();
65 }
66 
67 
68 //-----------------------------------------------------------------------------
69 // Destructor
70 //-----------------------------------------------------------------------------
71 
79 
81 {
82  release();
83 }
84 
85 
86 //-----------------------------------------------------------------------------
87 // Release current application
88 //-----------------------------------------------------------------------------
89 
98 
100 {
101  mMemLock.acquire();
102  if (mSharedMem.isAttached()) mSharedMem.detach();
103  mMemLock.release();
104 }
105 
106 
107 //-----------------------------------------------------------------------------
108 // Generate hash string
109 //-----------------------------------------------------------------------------
110 
120 
121 QString RunGuard::generateKeyHash( const QString& key, const QString& salt )
122 {
123  QByteArray data;
124 
125  data.append( key.toUtf8() );
126  data.append( salt.toUtf8() );
127  data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex();
128 
129  return data;
130 }
131 
132 
133 //-----------------------------------------------------------------------------
134 // Check whether antoher instance is running
135 //-----------------------------------------------------------------------------
136 
147 
148 bool RunGuard::anotherInstanceIsRunning (bool showMessage)
149 {
150  // If the shared memory is already attached to the own instance
151  // there is certainly no other application running.
152  if (mSharedMem.isAttached()) return false;
153 
154  // Otherwise, we have to check whether another instance has
155  // already created the shared memory. To find that out we
156  // try to attach ourselves. If this is possible
157  // it indicates that another application has already created the
158  // shared memory. If so, we detach immediately afterwards.
159  mMemLock.acquire();
160  const bool sharedMemAlreadyExists = mSharedMem.attach();
161  if (sharedMemAlreadyExists) mSharedMem.detach();
162  mMemLock.release();
163 
164  // Show an error message
165  if (sharedMemAlreadyExists and showMessage)
166  {
167  QMessageBox msgBox;
168  msgBox.setWindowTitle(tr("Information"));
169  msgBox.setText(tr("Just Intonation is already running."));
170  msgBox.setInformativeText(tr("Please close the application before restarting."));
171  msgBox.setStandardButtons(QMessageBox::Ok);
172  msgBox.setDefaultButton(QMessageBox::Ok);
173  msgBox.setIcon(QMessageBox::Information);
174  msgBox.exec();
175  }
176  return sharedMemAlreadyExists;
177 }
178 
RunGuard(const QString &mKey)
Constructor for a runguard.
Definition: runguard.cpp:48
QString generateKeyHash(const QString &mKey, const QString &salt)
Generate hash string for a given keys.
Definition: runguard.cpp:121
void release()
Release the running application.
Definition: runguard.cpp:99
QSharedMemory mSharedMem
Shared memory labelled by a given key.
Definition: runguard.h:68
~RunGuard()
RunGuard destructor.
Definition: runguard.cpp:80
bool anotherInstanceIsRunning(bool showMessage=true)
Check whether another instance of the application is running.
Definition: runguard.cpp:148
QSystemSemaphore mMemLock
Lock used when shared memory is accessed.
Definition: runguard.h:69
const QString mSharedMemKey
Key labelling the shared memory.
Definition: runguard.h:67