std:: counting_semaphore, std:: binary_semaphore
|
Определено в заголовочном файле
<semaphore>
|
||
|
template
<
std::
ptrdiff_t
LeastMaxValue
=
/* implementation-defined */
>
class counting_semaphore ; |
(1) | (since C++20) |
|
using
binary_semaphore
=
std
::
counting_semaphore
<
1
>
;
|
(2) | (since C++20) |
counting_semaphore
— это облегчённый примитив синхронизации, который может контролировать доступ к общему ресурсу. В отличие от
std::mutex
, семафор-счётчик
counting_semaphore
позволяет более чем одному одновременному доступу к одному и тому же ресурсу, как минимум для
LeastMaxValue
одновременных обращений. Программа некорректна, если
LeastMaxValue
является отрицательным.
binary_semaphore
является псевдонимом для специализации
std::counting_semaphore
с
LeastMaxValue
равным
1
. Реализации могут реализовывать
binary_semaphore
более эффективно, чем стандартная реализация
std::counting_semaphore
.
Семафор счётчика
counting_semaphore
содержит внутренний счётчик, инициализируемый конструктором. Этот счётчик уменьшается при вызовах
acquire()
и связанных методов, и увеличивается при вызовах
release()
. Когда счётчик равен нулю,
acquire()
блокируется до тех пор, пока счётчик не будет увеличен, однако
try_acquire()
не блокируется;
try_acquire_for()
и
try_acquire_until()
блокируются до увеличения счётчика или достижения таймаута.
Подобно
std::condition_variable::wait()
,
counting_semaphore
's
try_acquire()
может ложно завершаться неудачей.
Специализации
std::counting_semaphore
не являются
DefaultConstructible
,
CopyConstructible
,
MoveConstructible
,
CopyAssignable
или
MoveAssignable
.
Содержание |
Члены данных
| Название члена | Определение |
counter
(private)
|
Внутренний счетчик типа
std::ptrdiff_t
.
( объект-член только для демонстрации* ) |
Функции-члены
конструирует
counting_semaphore
(публичная функция-член) |
|
уничтожает
counting_semaphore
(публичная функция-член) |
|
|
operator=
[deleted]
|
counting_semaphore
не может быть присвоен
(публичная функция-член) |
Операции |
|
|
увеличивает внутренний счетчик и разблокирует ожидающих
(публичная функция-член) |
|
|
уменьшает внутренний счетчик или блокируется до возможности
(публичная функция-член) |
|
|
пытается уменьшить внутренний счетчик без блокировки
(публичная функция-член) |
|
|
пытается уменьшить внутренний счетчик, блокируясь на указанное время
(публичная функция-член) |
|
|
пытается уменьшить внутренний счетчик, блокируясь до указанного момента времени
(публичная функция-член) |
|
Константы |
|
|
[static]
|
возвращает максимально возможное значение внутреннего счетчика
(публичная статическая функция-член) |
Примечания
Как следует из названия,
LeastMaxValue
является
минимальным
максимальным значением, а не
фактическим
максимальным значением. Следовательно,
max()
может возвращать число большее, чем
LeastMaxValue
.
В отличие от
std::mutex
,
counting_semaphore
не привязан к потокам выполнения - захват семафора может происходить в другом потоке, чем освобождение семафора, например. Все операции с
counting_semaphore
могут выполняться конкурентно и без какой-либо привязки к конкретным потокам выполнения, за исключением деструктора, который не может выполняться конкурентно, но может быть выполнен в другом потоке.
Семафоры также часто используются для семантики сигнализации/уведомления, а не для взаимного исключения, путем инициализации семафора значением 0 и, таким образом, блокировки получателей, пытающихся вызвать acquire() , до тех пор пока отправитель не "подаст сигнал" путем вызова release ( n ) . В этом отношении семафоры можно рассматривать как альтернативу std::condition_variable , часто с более высокой производительностью.
| Макрос тестирования возможностей | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_lib_semaphore
|
201907L
|
(C++20) |
std::counting_semaphore
,
std::binary_semaphore
|
Пример
#include <chrono> #include <iostream> #include <semaphore> #include <thread> // глобальные экземпляры бинарного семафора // счетчики объектов установлены в ноль // объекты находятся в неподписанном состоянии std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // ожидание сигнала от основного процесса // путем попытки уменьшить счетчик семафора smphSignalMainToThread.acquire(); // этот вызов блокируется до тех пор, пока счетчик семафора // не будет увеличен из основного процесса std::cout << "[thread] Got the signal\n"; // ответное сообщение // ожидание 3 секунды для имитации // выполнения работы потоком using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // сообщение // сигнализировать основному процессу smphSignalThreadToMain.release(); } int main() { // создать рабочий поток std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // сообщение // сигнализировать рабочему потоку начать работу // путем увеличения счетчика семафора smphSignalMainToThread.release(); // ожидать завершения работы рабочим потоком // путем попытки уменьшить счетчик семафора smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // ответное сообщение thrWorker.join(); }
Вывод:
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal