std::counting_semaphore, std::binary_semaphore
Определено в заголовке <semaphore> | ||
|---|---|---|
template< std::ptrdiff_t LeastMaxValue = /* implementation-defined */ > class counting_semaphore; | (1) | (с C++20) |
using binary_semaphore = std::counting_semaphore<1>; | (2) | (с C++20) |
LeastMaxValue одновременных пользователей. Программа неверна, если LeastMaxValue отрицательно.binary_semaphore — это псевдоним для специализации std::counting_semaphore, где LeastMaxValue равно 1. Реализации могут реализовать binary_semaphore более эффективно, чем по умолчанию для std::counting_semaphore. Счётный семафор содержит внутренний счётчик, инициализированный конструктором. Этот счётчик уменьшается при вызовах acquire() и связанных с ним методах, и увеличивается при вызовах release(). Когда счётчик равен нулю, acquire() блокируется до тех пор, пока счётчик не увеличится, но try_acquire() не блокируется; try_acquire_for() и try_acquire_until() блокируются до тех пор, пока счётчик не увеличится или не будет достигнут таймаут.
Аналогично std::condition_variable::wait(), случайная неудача возможна в работе counting_semaphore с try_acquire().
Специализации std::counting_semaphore не являются DefaultConstructible, CopyConstructible, MoveConstructible, CopyAssignable или MoveAssignable.
Члены-функции
| создаёт счётный семафор (публичный член-функция) |
|
| уничтожает счётный семафор (публичный член-функция) |
|
| operator=
[удалено] | Присвоение счётного семафора недоступно (публичный член-функция) |
Операции |
|
| увеличивает внутренний счётчик и разблокирует ожидающих доступа (публичный член-функция) |
|
| уменьшает внутренний счётчик или блокируется до тех пор, пока это возможно (публичный член-функция) |
|
| пытается уменьшить внутренний счётчик, не блокируясь (публичный член-функция) |
|
| пытается уменьшить внутренний счётчик, блокируясь на заданный период времени (публичный член-функция) |
|
| пытается уменьшить внутренний счётчик, блокируясь до заданного момента времени (публичный член-функция) |
|
Константы |
|
|
[статический] | возвращает максимально возможное значение внутреннего счётчика (публичная статическая член-функция) |
Примечания
Как следует из названия, LeastMaxValue — это минимальное максимальное значение, а не фактическое максимальное значение. Поэтому max() может дать число, большее, чем LeastMaxValue.
В отличие от std::mutex, счётный семафор не привязан к потокам выполнения — получение семафора может происходить в одном потоке, а освобождение — в другом, например. Все операции со счётным семафором могут выполняться параллельно и не зависят от конкретных потоков выполнения, за исключением деструктора, который не может выполняться параллельно, но может выполняться в другом потоке.
Семафоры также часто используются для семантики сигнализации/уведомления, а не взаимной исключительности, инициализируя семафор значением 0 и тем самым блокируя получателя(ей), пытающегося acquire(), пока уведомление не «сигнализирует», вызвав release(n). В этом отношении семафоры могут рассматриваться как альтернатива std::condition_variable с лучшей производительностью.
| Макро-тест функции | Значение | Std | Функция |
|---|---|---|---|
__cpp_lib_semaphore | 201907L | (C++20) |
std::counting_semaphore, std::binary_semaphore |
Пример
#include <chrono>
#include <iostream>
#include <semaphore>
#include <thread>
// global binary semaphore instances
// object counts are set to zero
// objects are in non-signaled state
std::binary_semaphore
smphSignalMainToThread{0},
smphSignalThreadToMain{0};
void ThreadProc()
{
// wait for a signal from the main proc
// by attempting to decrement the semaphore
smphSignalMainToThread.acquire();
// this call blocks until the semaphore's count
// is increased from the main proc
std::cout << "[thread] Got the signal\n"; // response message
// wait for 3 seconds to imitate some work
// being done by the thread
using namespace std::literals;
std::this_thread::sleep_for(3s);
std::cout << "[thread] Send the signal\n"; // message
// signal the main proc back
smphSignalThreadToMain.release();
}
int main()
{
// create some worker thread
std::thread thrWorker(ThreadProc);
std::cout << "[main] Send the signal\n"; // message
// signal the worker thread to start working
// by increasing the semaphore's count
smphSignalMainToThread.release();
// wait until the worker thread is done doing the work
// by attempting to decrement the semaphore's count
smphSignalThreadToMain.acquire();
std::cout << "[main] Got the signal\n"; // response message
thrWorker.join();
}Вывод:
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/counting_semaphore