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) |
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(), вызов try_acquire() у counting_semaphore может завершиться неудачей без причины.
Специализации std::counting_semaphore не удовлетворяют требованиям DefaultConstructible, CopyConstructible, MoveConstructible, CopyAssignable или MoveAssignable.
Поля
| Имя поля | Определение |
|---|---|
counter (закрытое) | Внутренний счётчик типа std::ptrdiff_t.(объект-член только для экспозиции*) |
Функции-члены
создаёт counting_semaphore (открытая функция-член) |
|
уничтожает counting_semaphore (открытая функция-член) |
|
|
operator=
[удалён] |
counting_semaphore нельзя присваивать (открытая функция-член) |
Операции |
|
| увеличивает внутренний счётчик и разблокирует ожидающие потоки (открытая функция-член) |
|
| уменьшает внутренний счётчик или блокируется до появления такой возможности (открытая функция-член) |
|
| пытается уменьшить внутренний счётчик, не блокируясь (открытая функция-член) |
|
| пытается уменьшить внутренний счётчик, блокируясь на время не более указанного интервала (открытая функция-член) |
|
| пытается уменьшить внутренний счётчик, блокируясь до указанного момента времени (открытая функция-член) |
|
Константы |
|
|
[статический] | возвращает максимально возможное значение внутреннего счётчика (открытая статическая функция-член) |
Примечания
Как следует из названия, 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>
// 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/cpp/thread/counting_semaphore