dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
runguard.cpp
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  *
27  * Additional note on redistribution: The copyright and license notices above
28  * must be maintained in each individual source file that is a derivative work
29  * of this source file; otherwise redistribution is prohibited.
30  */
31 
32 #include "runguard.h"
33 
34 #include <QCryptographicHash>
35 
36 namespace {
37 
38 QString generateKeyHash(const QString &key, const QString &salt)
39 {
40  QByteArray data;
41 
42  data.append(key.toUtf8());
43  data.append(salt.toUtf8());
44  data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
45 
46  return data;
47 }
48 }
49 
50 RunGuard::RunGuard(const QString &key)
51  : key(key)
52  , memLockKey(generateKeyHash(key, "_memLockKey"))
53  , sharedmemKey(generateKeyHash(key, "_sharedmemKey"))
54  , sharedMem(sharedmemKey)
55  , memLock(memLockKey, 1)
56 {
57  memLock.acquire();
58  {
59  QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/
60  fix.attach();
61  }
62  memLock.release();
63 }
64 
65 RunGuard::~RunGuard()
66 {
67  release();
68 }
69 
70 RunGuard &RunGuard::instance(const QString &key)
71 {
72  static RunGuard instance(key);
73  return instance;
74 }
75 
76 bool RunGuard::isAnotherRunning()
77 {
78  if (sharedMem.isAttached())
79  return false;
80 
81  memLock.acquire();
82  const bool isRunning = sharedMem.attach();
83  if (isRunning) {
84  *static_cast<quint64 *>(sharedMem.data()) += 1;
85  sharedMem.detach();
86  }
87  memLock.release();
88 
89  return isRunning;
90 }
91 
93 {
94  if (isAnotherRunning()) // Extra check
95  return false;
96 
97  memLock.acquire();
98  const bool result = sharedMem.create(sizeof(quint64));
99  if (result)
100  *static_cast<quint64 *>(sharedMem.data()) = 0;
101  memLock.release();
102  if (!result) {
103  release();
104  return false;
105  }
106 
107  return true;
108 }
109 
111 {
112  quint64 ret = 0;
113  memLock.acquire();
114  if (!sharedMem.isAttached() && sharedMem.attach(QSharedMemory::ReadOnly)) {
115  ret = *static_cast<quint64 *>(sharedMem.data());
116  sharedMem.detach();
117  } else {
118  ret = *static_cast<quint64 *>(sharedMem.data());
119  }
120  memLock.release();
121  return ret;
122 }
123 
124 void RunGuard::release()
125 {
126  memLock.acquire();
127  if (sharedMem.isAttached())
128  sharedMem.detach();
129  memLock.release();
130 }
131 
bool tryToRun()
Attempt to run and fail if another instance is running.
Definition: runguard.cpp:92
DataFields data
quint64 secondaryAttempts()
Number of secondary instances attempted to start.
Definition: runguard.cpp:110
static RunGuard & instance(const QString &key)
Get instance of this singleton.
Definition: runguard.cpp:70