Espacios de nombres
Variantes
Acciones

std::counting_semaphore, std::binary_semaphore

De cppreference.com
< cpp‎ | thread
 
 
Biblioteca de apoyo de concurrencia
Hilos
(C++11)
(C++20)
Espacio de nombres this_thread
(C++11)
(C++11)
(C++11)
Cancelación cooperativa
Exclusión mutua
(C++11)
Gestión genérica de bloqueo
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Variables de condición
(C++11)
Semáforos
counting_semaphorebinary_semaphore
(C++20)(C++20)
Pestillos y barreras
(C++20)
(C++20)
Futuros
(C++11)
(C++11)
(C++11)
(C++11)
Recuperación segura
(C++26)
Punteros de riesgo
Tipos atómicos
(C++11)
(C++20)
Inicialización de tipos atómicos
(C++11)(en desuso en C++20)
(C++11)(en desuso en C++20)
Orden de memoria
Funciones independientes para operaciones atómicas
Funciones independientes para indicadores atómicos
 
 
Definido en el archivo de encabezado <semaphore>
template<std::ptrdiff_t LeastMaxValue = /* definido por la implementación */>
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 simultáneo al mismo recurso, para al menos LeastMaxValue accesores simultáneos. 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 predeterminada de std::counting_semaphore.

Un counting_semaphore contiene un contador interno inicializado por el constructor. Este contador se reduce mediante llamadas a acquire() y métodos relacionados, y se incrementa mediante llamadas a release(). Cuando el contador es cero, acquire() bloquea hasta que se incrementa el contador, pero try_acquire() no bloquea; try_acquire_for() y try_acquire_until() bloquean hasta que se incremente el contador o se alcance un tiempo de espera. Similar a std::condition_variable::wait(), try_acquire() de un counting_semaphore puede fallar falsamente (spuriously).

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

Contenido

[editar] Funciones miembro

Construye un objeto counting_semaphore
(función miembro pública) [editar]
Destruye el objeto counting_semaphore
(función miembro pública) [editar]
operator=
[eliminada]
counting_semaphore no es asignable
(función miembro pública) [editar]
Operaciones
Incrementa el contador interno y desbloquea a los adquiridores
(función miembro pública) [editar]
Decrementa el contador interno o se bloquea hasta que puede
(función miembro pública) [editar]
Trata de decrementar el contador interno sin bloquearse
(función miembro pública) [editar]
Trata de decrementar el contador interno bloqueándose hasta un tiempo límite de duración
(función miembro pública) [editar]
Trata de decrementar el contador interno, bloqueándose hasta un punto en el tiempo
(función miembro pública) [editar]
Constantes
[estático]
Devuelve el valor máximo posible del contador interno
(función miembro estática pública) [editar]

[editar] Notas

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

A diferencia de std::mutex, un counting_semaphore no está ligado a los hilos de ejecución; por ejemplo, la adquisición de un semáforo puede ocurrir en un hilo diferente a la liberación del semáforo. Todas las operaciones en counting_semaphore se pueden realizar al mismo tiempo y sin ninguna relación con hilos de ejecución específicos, con la excepción del destructor que no se puede realizar al mismo tiempo pero se puede realizar 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 la exclusión mutua, al inicializar el semáforo con 0 y, por lo tanto, bloquear los receptores que intentan adquirir mediante acquire(), hasta que el notificador "señale" invocando release(n). En este sentido, los semáforos pueden considerarse alternativas a las variables de condición, std::condition_variable, a menudo con mejor rendimiento.

[editar] Ejemplo

#include <iostream>
#include <thread>
#include <chrono>
#include <semaphore>
 
 
// instancias globales de semáforos binarios
// el conteo de objetos se establece a cero
// los objetos se encuentran en un estado no señalado
std::binary_semaphore
	smphSignalMainToThread(0),
	smphSignalThreadToMain(0);
 
void ThreadProc()
{	
	// esperar por una señal del proc principal
	// intentando decrementar el semáforo
	smphSignalMainToThread.acquire();
 
	// esta llamada se bloquea hasta que el conteo del semáforo
	// se incremente en el proc principal
 
	std::cout << "[thread] Obtuvo la señal\n"; // mensaje de respuesta
 
	// esperar 3 segundos para imitar algo de trabajo
	// hecho por el hilo
	using namespace std::literals;
	std::this_thread::sleep_for(3s);
 
	std::cout << "[thread] Mandar la señal\n"; // mensaje
 
	// señalar de vuelta al proc principal
	smphSignalThreadToMain.release();
}
 
int main()
{
	// crear un hilo obrero
	std::thread thrWorker(ThreadProc);
 
	std::cout << "[main] Mandar la señal\n"; // mensaje
 
	// señalar al hilo obrero que empiece a trabajar
	// incrementando la cuienta del semáforo
	smphSignalMainToThread.release();
 
	// esperar hasta que el hilo obrero termine de hacer el trabajo
	// intentando decrementar el conteo del semáforo
	smphSignalThreadToMain.acquire();
 
	std::cout << "[main] Obtuvo la señal\n"; // mensaje de respuesta
	thrWorker.join();
}

Salida:

[main] Mandar la señal
[thread] Obtuvo la señal
[thread] Mandar la señal
[main] Obtuvo la señal