Класс QSystemSemaphore
Класс QSystemSemaphore предоставляет общий семафор со счётчиком. Подробнее...
| Заголовок: | #include <QSystemSemaphore> |
| CMake: | find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
Типы публичного доступа
| перечисление | AccessMode { Open, Create } |
| перечисление | SystemSemaphoreError { NoError, PermissionDenied, KeyError, AlreadyExists, NotFound, …, UnknownError } |
Функции публичного доступа
| QSystemSemaphore(const QString &key, int initialValue = 0, QSystemSemaphore::AccessMode mode = Open) | |
| ~QSystemSemaphore() | |
| bool | acquire() |
| QSystemSemaphore::SystemSemaphoreError | error() const |
| QString | errorString() const |
| QString | key() const |
| bool | release(int n = 1) |
| void | setKey(const QString &key, int initialValue = 0, QSystemSemaphore::AccessMode mode = Open) |
Подробное описание
Семафор — это обобщение мьютекса. В то время как мьютекс можно заблокировать только один раз, семафор можно приобрести несколько раз. Как правило, семафор используется для защиты определённого количества одинаковых ресурсов.
Как и его более лёгкий аналог QSemaphore, к QSystemSemaphore можно получить доступ из нескольких потоков. В отличие от QSemaphore, к QSystemSemaphore также можно получить доступ из нескольких процессов. Это означает, что QSystemSemaphore — это более тяжёлый класс, поэтому, если вашему приложению не нужно обращаться к вашим семафорам через несколько процессов, вы, вероятно, захотите использовать QSemaphore.
Семафоры поддерживают две основные операции: acquire() и release():
acquire() пытается получить один ресурс. Если доступного ресурса нет, вызов блокируется до тех пор, пока ресурс не станет доступным. Затем ресурс приобретается, и вызов возвращается.
release() освобождает один ресурс, чтобы его мог получить другой процесс. Функция также может быть вызвана с параметром n > 1, который освобождает n ресурсов.
Семафор системы создаётся с строковым ключом, который другие процессы могут использовать для работы с тем же семафором.
Пример: Создание семафора системы
QSystemSemaphore sem("market", 3, QSystemSemaphore::Create);
// resources available == 3
sem.acquire(); // resources available == 2
sem.acquire(); // resources available == 1
sem.acquire(); // resources available == 0
sem.release(); // resources available == 1
sem.release(2); // resources available == 3 Типичное применение семафоров системы — управление доступом к кольцевому буферу, общий для процесса-производителя и процессов-потребителей.
Платформенно-специфическое поведение
При использовании этого класса следует учитывать следующие отличия между платформами:
Windows: QSystemSemaphore не владеет своим базовым семафором системы. Им владеет Windows. Это означает, что когда все экземпляры QSystemSemaphore для конкретного ключа были уничтожены, либо вызвав их деструкторы, либо из-за сбоя одного или нескольких процессов, Windows удаляет базовый семафор системы.
Unix:
- QSystemSemaphore владеет базовым семафором системы в системах Unix. Это означает, что последний процесс, имеющий экземпляр QSystemSemaphore для конкретного ключа, должен удалить базовый семафор системы в своём деструкторе. Если последний процесс завершается аварийно, не выполняя деструктор QSystemSemaphore, Unix не удаляет автоматически базовый семафор системы, и семафор сохраняется после сбоя. Последующий процесс, который создаёт QSystemSemaphore с тем же ключом, получит существующий семафор системы. В этом случае, если конструктор QSystemSemaphore указал свой режим доступа как Open, его начальное значение ресурса не будет сброшено до предоставленного, а останется установленным в значение, полученное в процессе сбоя. Для защиты от этого, первый процесс, создающий семафор для конкретного ключа (обычно сервер), должен передать свой режим доступа как Create, что заставит Unix сбросить значение ресурса в базовом семафоре системы.
- Когда процесс, использующий QSystemSemaphore, завершается по любой причине, Unix автоматически отменяет действие всех операций получения, которые не были освобождены. Таким образом, если процесс получает ресурс, а затем завершается без его освобождения, Unix освободит этот ресурс.
Платформы Apple: Приложения в защищённой среде (включая приложения, распространяемые через Apple App Store), требуют, чтобы ключ был в формате <application group identifier>/<custom identifier>, как указано здесь и здесь, и длина ключа ограничена 30 символами.
См. также QSharedMemory и QSemaphore.
Документация по типам членов
Перечисление QSystemSemaphore::AccessMode
Это перечисление используется конструктором и setKey(). Его назначение состоит в том, чтобы разрешить обработку проблемы в реализациях семафоров Unix, которые сохраняются после сбоя. В Unix, когда семафор сохраняется после сбоя, нам нужен способ принудительно сбросить счётчик ресурсов, когда система повторно использует семафор. В Windows, где семафоры не могут сохраниться после сбоя, это перечисление не оказывает влияния.
| Константа | Значение | Описание |
|---|---|---|
QSystemSemaphore::Open |
0 |
Если семафор уже существует, его начальное значение ресурса не сбрасывается. Если семафор ещё не существует, он создаётся, и его начальное значение ресурса устанавливается. |
QSystemSemaphore::Create |
1 |
QSystemSemaphore получает владение семафором и устанавливает его счётчик ресурсов в запрошенное значение, независимо от того, существует ли семафор уже, выжив после сбоя. Это значение следует передать в конструктор, когда первый семафор для конкретного ключа создаётся и известно, что если семафор уже существует, то это могло произойти только из-за сбоя. В Windows, где семафор не может сохраниться после сбоя, Create и Open имеют одинаковое поведение. |
Перечисление QSystemSemaphore::SystemSemaphoreError
| Константа | Значение | Описание |
|---|---|---|
QSystemSemaphore::NoError |
0 |
Ошибка не произошла. |
QSystemSemaphore::PermissionDenied |
1 |
Операция не удалась, потому что у вызывающего процесса не было необходимых разрешений. |
QSystemSemaphore::KeyError |
2 |
Операция не удалась из-за некорректного ключа. |
QSystemSemaphore::AlreadyExists |
3 |
Операция не удалась, потому что семафор системы с указанным ключом уже существовал. |
QSystemSemaphore::NotFound |
4 |
Операция не удалась, потому что семафор системы с указанным ключом не был найден. |
QSystemSemaphore::OutOfResources |
5 |
Операция не удалась из-за недостатка памяти для выполнения запроса. |
QSystemSemaphore::UnknownError |
6 |
Произошло что-то другое, и это было плохо. |
Документация по функциям членов
QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue = 0, QSystemSemaphore::AccessMode mode = Open)
Запрашивает семафор системы для указанного key. Параметры initialValue и mode используются в соответствии со следующими правилами, которые зависят от системы.
В Unix, если mode равен Open и система уже имеет семафор, идентифицируемый по key, используется этот семафор, и значение ресурса семафора не изменяется, т.е. initialValue игнорируется. Но если система ещё не имеет семафор, идентифицируемый по key, она создаёт новый семафор для этого ключа и устанавливает его счётчик ресурсов в initialValue.
В Unix, если режим равен Создать, а в системе уже есть семафор, идентифицируемый по ключу, используется этот семафор, и его счётчик ресурсов устанавливается в начальное значение. Если в системе ещё нет семафора, идентифицируемого по ключу, создаётся новый семафор для этого ключа, и его счётчик ресурсов устанавливается в начальное значение.
В Windows параметр режим игнорируется, и система всегда пытается создать семафор для указанного ключа. Если в системе ещё нет семафора, идентифицируемого как ключ, создаётся семафор, и его счётчик ресурсов устанавливается в начальное значение. Но если семафор с указанным ключом уже существует, используется этот семафор, а начальное значение игнорируется.
Параметр режим используется только в системах Unix для обработки случая, когда семафор сохраняется после сбоя процесса. В этом случае следующий процесс, который выделяет семафор с тем же ключом, получит семафор, сохранившийся после сбоя, и, если режим не равен Создать, счётчик ресурсов не будет сброшен до начального значения, а сохранит начальное значение, заданное аварийно завершившимся процессом.
QSystemSemaphore::~QSystemSemaphore()
Деструктор уничтожает объект QSystemSemaphore, но сам системный семафор не удаляется из системы, пока этот экземпляр QSystemSemaphore является последним существующим для этого системного семафора.
Два важных побочных эффекта деструктора зависят от системы. В Windows, если для этого семафора был вызван acquire(), но не release(), release() не будет вызван деструктором, и ресурс не будет освобождён при нормальном завершении процесса. Это будет ошибкой программы, которая может привести к тупику в другом процессе, пытающемся получить доступ к тому же ресурсу. В Unix, полученные ресурсы, которые не были освобождены перед вызовом деструктора, автоматически освобождаются при завершении процесса.
bool QSystemSemaphore::acquire()
Получает один из ресурсов, защищаемых этим семафором, если он доступен, и возвращает true. Если все ресурсы, защищаемые этим семафором, уже получены, вызов блокируется до тех пор, пока один из них не будет освобождён другим процессом или потоком, имеющим семафор с тем же ключом.
Если возвращается false, произошла системная ошибка. Вызовите error(), чтобы получить значение QSystemSemaphore::SystemSemaphoreError, которое указывает, какая ошибка произошла.
См. также release().
QSystemSemaphore::SystemSemaphoreError QSystemSemaphore::error() const
Возвращает значение, указывающее, произошла ли ошибка, и, если да, то какая именно.
См. также errorString().
QString QSystemSemaphore::errorString() const
Возвращает текстовое описание последней произошедшей ошибки. Если error() возвращает значение ошибки, вызовите эту функцию, чтобы получить текстовую строку, описывающую ошибку.
См. также error().
QString QSystemSemaphore::key() const
Возвращает ключ, назначенный этому системному семафору. Ключ — это имя, по которому семафор может быть доступен из других процессов.
См. также setKey().
bool QSystemSemaphore::release(int n = 1)
Освобождает n ресурсов, защищаемых семафором. Возвращает true за исключением системных ошибок.
Пример: Создайте системный семафор с пятью ресурсами; получите все ресурсы и затем освободите их все.
QSystemSemaphore sem("market", 5, QSystemSemaphore::Create);
for (int i = 0; i < 5; ++i) // acquire all 5 resources
sem.acquire();
sem.release(5); // release the 5 resources Эта функция также может "создавать" ресурсы. Например, сразу после последовательности операторов выше, предположим, что мы добавили оператор:
sem.release(10); // "create" 10 new resources
Теперь семафор защищает десять новых ресурсов в дополнение к уже существующим пяти. Обычно вы не будете использовать эту функцию для создания дополнительных ресурсов.
См. также acquire().
void QSystemSemaphore::setKey(const QString &key, int initialValue = 0, QSystemSemaphore::AccessMode mode = Open)
Эта функция работает так же, как и конструктор. Она пересоздаёт объект QSystemSemaphore. Если новый ключ отличается от старого, вызов этой функции эквивалентен вызову деструктора семафора со старым ключом, а затем вызову конструктора для создания нового семафора с новым ключом. Параметры initialValue и mode определены так же, как и для конструктора.
См. также QSystemSemaphore() и key().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/qsystemsemaphore.html