std:: counting_semaphore, std:: binary_semaphore
|
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) |
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.
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