Как стать автором
Обновить

Комментарии 24

Реализация QtSingleCoreApplication использует файл для межпроцессной блокировки [1].
А реализация @gcooler-а делает всё в памяти. Возможно для кого-то это критично.
И еще она QLocalSocket использует, насколько я могу видеть. Со всеми вытекающими преимуществами и недостатками.
Интересное решение, спасибо за ссылку!
Единственный недостаток который вижу — решение довольно «тяжеловесное», плюс тянет за собой QtNetwork. Я когда свое решение писал стремился всеми силами не вылезать за рамки QtCore+QtGui. Но в плане функциональности там одни преимущества, конечно, при случае попробую обязательно.
Но возникает проблема. Если пользователь запустит второй экземплар приложения — как он об этом узнает?
Проблемы нет. Если семафор уже создан, второй такой же создать не получится с соответствующим кодом ошибки. Это и служит критерием для различения ситуаций «первый запуск / последующие запуски».
Если вести речь о QSystemSemaphore, то его создать можно всегда, даже если он уже создан. Насколько я понимаю, начинка класса сама определяет делать, грубо говоря, «open» или «create».
Не важно. Важно то, что можно атомарно (без race condition) разделить две ситуации.
Я там ниже уже писал, насколько я понял документацию, далеко не всегда эти ситуации разделимы.

In Windows and in Symbian, where a semaphore can't survive a crash, Create and Open have the same behavior.


Но, повторюсь, спорить не буду, т.к. не пробовал.
Неправильно поняли документацию. На «Windows и Symbian», если приложение грохнулось, используемые ресурсы (например, семафоры) всегда будут освобождены. Это правильное, корректное поведение. На некоторых unix'ах это не всегда так, поэтому и приходится там делать дополнительные действия.

Цитата в переводе звучит примерно так:
«На Windows или Symbuan, где семафор освобождается в случае падения приложения, разницы между функциями Creare и Open нет».
Гм, так если нет разницы между Create и Open как же мы будем различать две ситуации?
На линуксе, кстати, в случае падения приложения QSharedMemory не разрушается — об этом я писал в тексте поста. Не удивлюсь если и семафоры линуксовые ведут себя так же. Вобщем все надо проверять.

М, кстати. Еще вспомнил из практики работы с QSystemSemaphore под линуксом. Семафор однажды созданный не может быть пересоздан (возможно только для случая краша прилоежния, но не суть важно). Кажется даже в документации это где-то отражено. Но я точно помню что один раз крепко напоролся на это. Поэтому скорее всего на одних семафорах работать не будет. А то стал бы я иначе такой огород городить…
Хм… Вообще, если QSystemSemaphore заявляет, что не умеет (на некоторых системах) определять, что семафор уже реально никем не используется — значит, его нельзя использовать для этой задачи (как минимум, на этих системах).
Вот поэтому я и собрал такой велосипед вокруг него…
Велосипеды городить не хотелось

Но таки нагородили, Первым комментарием ссылка на стандартное решение.
Странно что не нашли, ибо по запорсу «Create single instance application qt» вся первая страница выдачи
про QtSingleApplication
НЛО прилетело и опубликовало эту надпись здесь
Когда столкнулся с подобной задачей — решил её как через QLocalSocket
И в качестве бонуса можно сразу через этот сокет послать сообщение, вот только виндовый файрвол на такие штуки будет спрашивать разрешения.
Мне кажется надежнее сразу проверять LockFile, а потом по сокету, как это делает QtSingleApplication.
Не локфайл, а пидфайл. Но это костыль древний, несерьезно.
Но возникает проблема. Если пользователь запустит второй экземплар приложения — как он об этом узнает? Вызов метода acquire блокирующий и пока семафор не освободиться приложение будет «висеть», а пользователь в недоумении чего-то ждать.


Что-то в вашем решении не видно как вы обошли эту проблему.
И вообще, если их открывать с create, то во втором случае просто словишь error с QSystemSemaphore::AlreadyExists.
In Windows and in Symbian, where a semaphore can't survive a crash, Create and Open have the same behavior.


Есть ощущение что это не сработает. Хотя спорить не буду, надо будет попробовать сначала.
Если кратко — обошел ее вызовом метода release. Т.е. я говорю в тексте о том, что если использовать QSystemSemaphore для решения задачи — возникает такая проблема. В конечном варианте для решения я использую QSharedMemory, а QSystemSemaphore только лишь для синхронизации доступа к разделяемой памяти, поэтому означенная проблема и не возникает.
Поправил, спасибо!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории