Namespaces
Variants

std:: counting_semaphore, std:: binary_semaphore

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
counting_semaphore binary_semaphore
(C++20) (C++20)
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
Definido en el encabezado <semaphore>
template < std:: ptrdiff_t LeastMaxValue = /* implementation-defined */ >
class counting_semaphore ;
(1) (desde C++20)
using binary_semaphore = std :: counting_semaphore < 1 > ;
(2) (desde C++20)
1) Un counting_semaphore es una primitiva de sincronización ligera que puede controlar el acceso a un recurso compartido. A diferencia de un std::mutex , un counting_semaphore permite más de un acceso concurrente al mismo recurso, para al menos LeastMaxValue accesores concurrentes. El programa está mal formado si LeastMaxValue es negativo.
2) binary_semaphore es un alias para la especialización de std::counting_semaphore con LeastMaxValue siendo 1 . Las implementaciones pueden implementar binary_semaphore de manera más eficiente que la implementación por defecto de std::counting_semaphore .

Un counting_semaphore contiene un contador interno inicializado por el constructor. Este contador se decrementa mediante llamadas a acquire() y métodos relacionados, y se incrementa mediante llamadas a release() . Cuando el contador es cero, acquire() se bloquea hasta que el contador se incrementa, pero try_acquire() no se bloquea; try_acquire_for() y try_acquire_until() se bloquean hasta que el contador se incrementa o se alcanza un tiempo de espera.

Similar a std::condition_variable::wait() , counting_semaphore 's try_acquire() puede fallar espuriamente.

Las especializaciones de std::counting_semaphore no son DefaultConstructible , CopyConstructible , MoveConstructible , CopyAssignable , ni MoveAssignable .

Contenidos

Miembros de Datos

Nombre del miembro Definición
counter (privado) El contador interno de tipo std::ptrdiff_t .
( objeto miembro solo para exposición* )

Funciones miembro

construye un counting_semaphore
(función miembro pública)
destruye el counting_semaphore
(función miembro pública)
operator=
[deleted]
counting_semaphore no es asignable
(función miembro pública)
Operaciones
incrementa el contador interno y desbloquea a los adquirentes
(función miembro pública)
decrementa el contador interno o se bloquea hasta que sea posible
(función miembro pública)
intenta decrementar el contador interno sin bloquearse
(función miembro pública)
intenta decrementar el contador interno, bloqueándose hasta por un tiempo de duración
(función miembro pública)
intenta decrementar el contador interno, bloqueándose hasta un punto en el tiempo
(función miembro pública)
Constantes
[static]
devuelve el valor máximo posible del contador interno
(función miembro estática pública)

Notas

Como su nombre indica, el LeastMaxValue es el valor máximo mínimo , no el valor máximo real . Por lo tanto, max() puede producir un número mayor que LeastMaxValue .

A diferencia de std::mutex un counting_semaphore no está vinculado a hilos de ejecución - la adquisición de un semáforo puede ocurrir en un hilo diferente al que libera el semáforo, por ejemplo. Todas las operaciones en counting_semaphore pueden realizarse concurrentemente y sin ninguna relación con hilos de ejecución específicos, con la excepción del destructor que no puede realizarse concurrentemente pero sí puede ejecutarse en un hilo diferente.

Los semáforos también se utilizan a menudo para la semántica de señalización/notificación en lugar de exclusión mutua, inicializando el semáforo con 0 y así bloqueando al receptor(es) que intenta(n) acquire() , hasta que el notificador "señaliza" invocando release ( n ) . En este aspecto, los semáforos pueden considerarse alternativas a las std::condition_variable , frecuentemente con mejor rendimiento.

Macro de prueba de características Valor Std Característica
__cpp_lib_semaphore 201907L (C++20) std::counting_semaphore , std::binary_semaphore

Ejemplo

#include <chrono>
#include <iostream>
#include <semaphore>
#include <thread>
// instancias globales de semáforo binario
// los contadores de objetos están establecidos en cero
// los objetos están en estado no señalado
std::binary_semaphore
    smphSignalMainToThread{0},
    smphSignalThreadToMain{0};
void ThreadProc()
{
    // esperar una señal del proceso principal
    // intentando decrementar el semáforo
    smphSignalMainToThread.acquire();
    // esta llamada se bloquea hasta que el contador del semáforo
    // se incremente desde el proceso principal
    std::cout << "[thread] Got the signal\n"; // mensaje de respuesta
    // esperar 3 segundos para imitar trabajo
    // siendo realizado por el hilo
    using namespace std::literals;
    std::this_thread::sleep_for(3s);
    std::cout << "[thread] Send the signal\n"; // mensaje
    // señalizar de vuelta al proceso principal
    smphSignalThreadToMain.release();
}
int main()
{
    // crear un hilo trabajador
    std::thread thrWorker(ThreadProc);
    std::cout << "[main] Send the signal\n"; // mensaje
    // señalizar al hilo trabajador para que comience a trabajar
    // incrementando el contador del semáforo
    smphSignalMainToThread.release();
    // esperar hasta que el hilo trabajador termine su trabajo
    // intentando decrementar el contador del semáforo
    smphSignalThreadToMain.acquire();
    std::cout << "[main] Got the signal\n"; // mensaje de respuesta
    thrWorker.join();
}

Salida:

[main] Send the signal
[thread] Got the signal
[thread] Send the signal
[main] Got the signal