std::barrier
Definido en el archivo de encabezado <barrier> | ||
template<class CompletionFunction =/* véase más abajo */> class barrier; | (desde C++20) | |
La plantilla de clase std::barrier
(barrera) proporciona un mecanismo de coordinación de hilos que permite bloquear como máximo un número esperado de hilos hasta que el número esperado de hilos llegue a la barrera. A diferencia de latch, las barreras son reutilizables: una vez que los hilos que llegan se desbloquean desde el punto de sincronización de una fase de barrera, la misma barrera se puede reutilizar.
El tiempo de vida de un objeto barrera consiste en una secuencia de fases de barrera. Cada fase define un punto de sincronización de fase. Los hilos que llegan a la barrera durante la fase pueden bloquearse en el punto de sincronización de fase llamando a wait
, y se desbloquearán cuando se ejecute el paso de finalización de fase.
Una fase de barrera consta de los siguientes pasos:
- El conteo esperado se reduce con cada llamada a
arrive
oarrive_and_drop
. - Cuando el conteo esperado llega a cero, se ejecuta el paso de finalización de fase. El paso de finalización invoca el objeto función de finalización y desbloquea todos los hilos bloqueados en el punto de sincronización de fase. El final del paso de finalización fuertemente sucede-antes de los retornos de todas las llamadas que fueron desbloqueadas por el paso de finalización.
- Para la especialización
std::barrier<>
(usando el argumento de plantilla por defecto), el paso de finalización se ejecuta como parte de la llamada aarrive
oarrive_and_drop
que provocó que el conteo esperado llegara a cero. - Para otras especializaciones, el paso de finalización se ejecuta en uno de los hilos que llegaron a la barrera durante la fase, y el comportamiento no está definido si se llama a cualquiera de las funciones miembro del objeto barrera distintas de
wait
durante el paso de finalización.
- Para la especialización
- Cuando finaliza el paso de finalización, el conteo esperado se restablece al valor especificado en la construcción menos el número de llamadas a
arrive_and_drop
desde ese momento (de construcción), y comienza la siguiente fase de barrera.
Las invocaciones simultáneas de las funciones miembro de barrier
, a excepción del destructor, no introducen carreras de datos.
Contenido |
[editar]Parámetros de plantilla
CompletionFunction | - | Un tipo objeto función |
-CompletionFunction debe satisfacer los requisitos de MoveConstructible y Destructible. std::is_nothrow_invocable_v<CompletionFunction&> debe ser true. |
El argumento de plantilla predeterminado de CompletionFunction
es un tipo de objeto función no especificado que además cumple con los requisitos de DefaultConstructible. Llamar a un l-valor sin argumentos no tiene ningún efecto.
Cada objeto de tipo barrier
se comporta como si tuviese un dato miembro no estático completion_
de solo exposición de tipo CompletionFunction
y lo llama mediante completion_() en cada paso de la fase de finalización.
[editar]Tipos miembro
Nombre | Defiinición |
arrival_token | Un tipo objeto no especificado que cumple con los requisitos de MoveConstructible, MoveAssignable y Destructible |
[editar]Funciones miembro
Construye un objeto barrier (barrera) (función miembro pública) | |
Destruye el objeto barrier (barrera) (función miembro pública) | |
operator= [eliminada] | barrier no es asignable (función miembro pública) |
Llega a la barrera y decrementa el conteo esperado (función miembro pública) | |
Se bloquea en el punto de sincronización de fase hasta que se ejecute su paso de finalización de fase (función miembro pública) | |
Llega a la barrera y decrementa en uno el conteo esperado, luego se bloquea hasta que la fase actual se completa (función miembro pública) | |
Decrementa en uno tanto el conteo inicial esperado para fases subsecuentes, como el conteo esperado para la fase actual (función miembro pública) | |
Constantes | |
[estático] | El valor máximo del conteo esperado soportado por la implementación (función miembro estática pública) |
[editar]Ejemplo
#include <barrier>#include <iostream>#include <string>#include <thread>#include <vector> int main(){constauto workers ={"Ana", "Beto", "Carlos"}; auto on_completion =[]()noexcept{// aquí no se necesita bloquearstaticauto phase ="... listo\n""Limpiando...\n";std::cout<< phase; phase ="... listo\n";}; std::barrier sync_point(std::ssize(workers), on_completion); auto work =[&](std::string name){std::string product =" "+ name +" ha trabajado\n";std::cout<< product;// de acuerdo, la llamada a op<< es atómica sync_point.arrive_and_wait(); product =" "+ name +" ha limpiado\n";std::cout<< product; sync_point.arrive_and_wait();}; std::cout<<"Iniciando...\n";std::vector<std::thread> threads;for(autoconst& worker : workers){ threads.emplace_back(work, worker);}for(auto& thread : threads){ thread.join();}}
Posible salida:
Iniciando... Ana ha trabajado Carlos ha trabajado Beto ha trabajado ... listo Limpiando... Beto ha limpiado Carlos ha limpiado Ana ha limpiado ... listo
[editar]Véase también
(C++20) | Barrera de hilos de un solo uso. (clase) |