Класс 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, что принудительно сбросит счётчик ресурсов в лежащем в основе системном семафоре.
- При завершении процесса, использующего QSystemSemaphore по какой-либо причине, Unix автоматически отменяет действие всех операций acquire, которые не были освобождены. Таким образом, если процесс приобретает ресурс и затем завершается, не освободив его, Unix освободит этот ресурс.
См. также 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, если mode равен Create и системный семафор с идентификатором key уже существует, используется этот семафор, и его счётчик ресурсов устанавливается в initialValue. Если системный семафор с идентификатором key ещё не существует, создаётся новый семафор с этим ключом и устанавливается его счётчик ресурсов в initialValue.
В Windows параметр mode игнорируется, и система всегда пытается создать семафор для указанного key. Если в системе ещё нет семафора, идентифицированного как key, система создаёт семафор и устанавливает его счётчик ресурсов на initialValue. Но если семафор, идентифицированный как key, уже существует, система использует этот семафор и игнорирует initialValue.
Параметр mode используется только в системах Unix, чтобы обработать случай, когда семафор переживает сбой процесса. В этом случае следующий процесс, который выделит семафор с тем же key, получит семафор, переживший сбой, и если mode не Create, счётчик ресурсов не будет сброшен до initialValue, а сохранит значение, которое ему было присвоено аварийно завершившимся процессом.
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. Если новый key отличается от старого ключа, вызов этой функции аналогичен вызову деструктора семафора со старым ключом, за которым следует вызов конструктора для создания нового семафора с новым key. Параметры initialValue и mode определены так же, как и для конструктора.
См. также QSystemSemaphore() и key().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qsystemsemaphore.html