Класс QSystemSemaphore
Класс QSystemSemaphore предоставляет общее счетное системное семафор. Подробнее...
| Заголовок: | #include <QSystemSemaphore> |
| qmake: | QT += core |
| С тех пор: | Qt 4.4 |
Этот класс был представлен в Qt 4.4.
Типы публичного интерфейса
| перечисление | 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 автоматически отменяет действие всех операций 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-5.15/qsystemsemaphore.html