vsingleinstanceguard.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "vsingleinstanceguard.h"
  2. #include <QDebug>
  3. #include "utils/vutils.h"
  4. const QString VSingleInstanceGuard::c_memKey = "vnote_shared_memory";
  5. const int VSingleInstanceGuard::c_magic = 19910906;
  6. VSingleInstanceGuard::VSingleInstanceGuard()
  7. : m_online(false),
  8. m_sharedMemory(c_memKey)
  9. {
  10. }
  11. bool VSingleInstanceGuard::tryRun()
  12. {
  13. m_online = false;
  14. // If we can attach to the sharedmemory, there is another instance running.
  15. // In Linux, crashes may cause the shared memory segment remains. In this case,
  16. // this will attach to the old segment, then exit, freeing the old segment.
  17. if (m_sharedMemory.attach()) {
  18. qDebug() << "another instance is running";
  19. return false;
  20. }
  21. // Try to create it.
  22. bool ret = m_sharedMemory.create(sizeof(SharedStruct));
  23. if (ret) {
  24. // We created it.
  25. m_sharedMemory.lock();
  26. SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
  27. str->m_magic = c_magic;
  28. str->m_filesBufIdx = 0;
  29. str->m_askedToShow = false;
  30. m_sharedMemory.unlock();
  31. m_online = true;
  32. return true;
  33. } else {
  34. qDebug() << "fail to create shared memory segment";
  35. return false;
  36. }
  37. }
  38. void VSingleInstanceGuard::openExternalFiles(const QStringList &p_files)
  39. {
  40. if (p_files.isEmpty()) {
  41. return;
  42. }
  43. if (!m_sharedMemory.isAttached()) {
  44. if (!m_sharedMemory.attach()) {
  45. qDebug() << "fail to attach to the shared memory segment"
  46. << (m_sharedMemory.error() ? m_sharedMemory.errorString() : "");
  47. return;
  48. }
  49. }
  50. qDebug() << "try to request another instance to open files" << p_files;
  51. int idx = 0;
  52. int tryCount = 100;
  53. while (tryCount--) {
  54. qDebug() << "set shared memory one round" << idx << "of" << p_files.size();
  55. m_sharedMemory.lock();
  56. SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
  57. V_ASSERT(str->m_magic == c_magic);
  58. for (; idx < p_files.size(); ++idx) {
  59. if (p_files[idx].size() + 1 > FilesBufCount) {
  60. qDebug() << "skip file since its long name" << p_files[idx];
  61. // Skip this long long name file.
  62. continue;
  63. }
  64. if (!appendFileToBuffer(str, p_files[idx])) {
  65. break;
  66. }
  67. }
  68. m_sharedMemory.unlock();
  69. if (idx < p_files.size()) {
  70. VUtils::sleepWait(500);
  71. } else {
  72. break;
  73. }
  74. }
  75. }
  76. bool VSingleInstanceGuard::appendFileToBuffer(SharedStruct *p_str, const QString &p_file)
  77. {
  78. if (p_file.isEmpty()) {
  79. return true;
  80. }
  81. int strSize = p_file.size();
  82. if (strSize + 1 > FilesBufCount - p_str->m_filesBufIdx) {
  83. qDebug() << "no enough space for" << p_file;
  84. return false;
  85. }
  86. // Put the size first.
  87. p_str->m_filesBuf[p_str->m_filesBufIdx++] = (ushort)strSize;
  88. const QChar *data = p_file.constData();
  89. for (int i = 0; i < strSize; ++i) {
  90. p_str->m_filesBuf[p_str->m_filesBufIdx++] = data[i].unicode();
  91. }
  92. qDebug() << "after appended one file" << p_str->m_filesBufIdx << p_file;
  93. return true;
  94. }
  95. QStringList VSingleInstanceGuard::fetchFilesToOpen()
  96. {
  97. QStringList files;
  98. if (!m_online) {
  99. return files;
  100. }
  101. Q_ASSERT(m_sharedMemory.isAttached());
  102. m_sharedMemory.lock();
  103. SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
  104. Q_ASSERT(str->m_magic == c_magic);
  105. Q_ASSERT(str->m_filesBufIdx <= FilesBufCount);
  106. int idx = 0;
  107. while (idx < str->m_filesBufIdx) {
  108. int strSize = str->m_filesBuf[idx++];
  109. Q_ASSERT(strSize <= str->m_filesBufIdx - idx);
  110. QString file;
  111. for (int i = 0; i < strSize; ++i) {
  112. file.append(QChar(str->m_filesBuf[idx++]));
  113. }
  114. files.append(file);
  115. }
  116. str->m_filesBufIdx = 0;
  117. m_sharedMemory.unlock();
  118. return files;
  119. }
  120. void VSingleInstanceGuard::showInstance()
  121. {
  122. if (!m_sharedMemory.isAttached()) {
  123. if (!m_sharedMemory.attach()) {
  124. qDebug() << "fail to attach to the shared memory segment"
  125. << (m_sharedMemory.error() ? m_sharedMemory.errorString() : "");
  126. return;
  127. }
  128. }
  129. m_sharedMemory.lock();
  130. SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
  131. V_ASSERT(str->m_magic == c_magic);
  132. str->m_askedToShow = true;
  133. m_sharedMemory.unlock();
  134. qDebug() << "try to request another instance to show up";
  135. }
  136. bool VSingleInstanceGuard::fetchAskedToShow()
  137. {
  138. if (!m_online) {
  139. return false;
  140. }
  141. Q_ASSERT(m_sharedMemory.isAttached());
  142. m_sharedMemory.lock();
  143. SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
  144. Q_ASSERT(str->m_magic == c_magic);
  145. bool ret = str->m_askedToShow;
  146. str->m_askedToShow = false;
  147. m_sharedMemory.unlock();
  148. return ret;
  149. }
  150. void VSingleInstanceGuard::exit()
  151. {
  152. if (!m_online) {
  153. return;
  154. }
  155. Q_ASSERT(m_sharedMemory.isAttached());
  156. m_sharedMemory.detach();
  157. m_online = false;
  158. }