Класс QSystemSemaphore
Класс QSystemSemaphore предоставляет общий семафор со счётчиком. Подробнее...
| Заголовок: | #include <QSystemSemaphore> |
| qmake: | QT += core |
| С тех пор: | Qt 4.4 |
Этот класс был представлен в Qt 4.4.
Типы публичного доступа
| перечисление | AccessMode { Открыт, Создать } |
| перечисление | SystemSemaphoreError { НетОшибки, НетДоступа, НеверныйКлюч, УжеСуществует, ..., НеизвестнаяОшибка } |
Публичные функции
| 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 указал режим доступа AccessMode как Открыт, его начальное значение счётчика ресурсов не будет сброшено до заданного значения, а останется равным значению, полученному в аварийно завершившем работу процессе. Для защиты от этого первый процесс, создающий семафор для определённого ключа (обычно сервер), должен передать режим доступа AccessMode как Создать, что заставит Unix сбросить счётчик ресурсов в базовом системном семафоре.
- Когда процесс, использующий QSystemSemaphore, завершается по любой причине, Unix автоматически отменяет действие всех операций получения, которые не были освобождены. Таким образом, если процесс получает ресурс, а затем завершается, не освободив его, 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 равен Открыт и система уже имеет семафор с идентификатором key, используется этот семафор, и значение счётчика ресурсов семафора не изменяется, то есть initialValue игнорируется. Но если система ещё не имеет семафора с идентификатором key, она создаёт новый семафор для этого ключа и устанавливает его счётчик ресурсов в initialValue.
В Unix, если режим равен Создать и в системе уже есть семафор, идентифицированный по ключу, используется этот семафор, а его счетчик ресурсов устанавливается в значение initialValue. Если в системе ещё нет семафора с заданным ключом, создаётся новый семафор для этого ключа, и его счетчик ресурсов устанавливается в initialValue.
В Windows параметр режим игнорируется, и система всегда пытается создать семафор для указанного ключа. Если в системе ещё нет семафора с заданным ключом, создаётся семафор, и его счетчик ресурсов устанавливается в initialValue. Но если в системе уже есть семафор с заданным ключом, используется этот семафор, а initialValue игнорируется.
Параметр режима используется только в системах Unix для обработки случаев, когда семафор сохраняется после сбоя процесса. В этом случае следующий процесс, который выделит семафор с тем же ключом, получит семафор, который сохранился после сбоя, и если режим не равен Создать, счётчик ресурсов не будет сброшен до 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. Если новый ключ отличается от старого, вызов этой функции аналогичен вызову деструктора семафора со старым ключом, а затем вызову конструктора для создания нового семафора с новым ключом. Параметры initialValue и mode определены так же, как и для конструктора.
См. также QSystemSemaphore() и key().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/qsystemsemaphore.html