Spec-Zone.ru › C++

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)
1) counting_semaphore — это лёгкий примитив синхронизации, который может управлять доступом к общему ресурсу. В отличие от std::mutex, counting_semaphore допускает более одного одновременного доступа к одному и тому же ресурсу — не менее LeastMaxValue одновременных обращений. Программа некорректна, если LeastMaxValue отрицательно.
2) 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.
(объект-член только для экспозиции*)

Функции-члены

(constructor)
создаёт counting_semaphore
(открытая функция-член)
(destructor)
уничтожает counting_semaphore
(открытая функция-член)
operator=
[удалён]
counting_semaphore нельзя присваивать
(открытая функция-член)
Операции
release
увеличивает внутренний счётчик и разблокирует ожидающие потоки
(открытая функция-член)
acquire
уменьшает внутренний счётчик или блокируется до появления такой возможности
(открытая функция-член)
try_acquire
пытается уменьшить внутренний счётчик, не блокируясь
(открытая функция-член)
try_acquire_for
пытается уменьшить внутренний счётчик, блокируясь на время не более указанного интервала
(открытая функция-член)
try_acquire_until
пытается уменьшить внутренний счётчик, блокируясь до указанного момента времени
(открытая функция-член)
Константы
max
[статический]
возвращает максимально возможное значение внутреннего счётчика
(открытая статическая функция-член)

Примечания

Как следует из названия, 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API