Класс QSystemSemaphore
Класс QSystemSemaphore предоставляет общее счётное системное семафор. Подробнее...
| Заголовок: | #include <QSystemSemaphore> |
| qmake: | QT += core |
| С тех пор: | Qt 4.4 |
Открытые типы
| перечисление | AccessMode { Open, Create } |
| перечисление | SystemSemaphoreError { NoError, PermissionDenied, KeyError, AlreadyExists, ..., 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) |
Подробное описание
Класс QSystemSemaphore предоставляет общее счётное системное семафор.
Семафор является обобщением мьютекса. В то время как мьютекс может быть заблокирован только один раз, семафор может быть получен несколько раз. Как правило, семафор используется для защиты определённого количества идентичных ресурсов.
Как и его более лёгкий аналог QSemaphore, QSystemSemaphore может быть доступен из нескольких потоков threads. В отличие от QSemaphore, QSystemSemaphore также может быть доступен из нескольких процессов processes. Это означает, что 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 автоматически отменяет действие всех операций 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, если режим равен Создать и в системе уже есть семафор, идентифицированный по ключу, используется этот семафор, а его счетчик ресурсов устанавливается в значение 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.12/qsystemsemaphore.html