std::call_once
Definido en el archivo de encabezado <mutex>
|
||
template< class Callable, class... Args > void call_once( std::once_flag& flag, Callable&& f, Args&&... args ); |
(desde C++11) | |
Ejecuta el objeto invocable (Callable) f
exactamente una vez, incluso si se llama concurrentemente desde varios hilos.
En detalle:
- Si para el momento en que se llama a
call_once
,flag
indica quef
ya se llamó,call_once
regresa de inmediato (tal llamada acall_once
se conoce como pasiva).
- De lo contrario,
call_once
invoca a std::forward<Callable>(f) con los argumentos std::forward<Args>(args)... (como si fuera por std::invoke). A diferencia del constructor de std::thread o std::async, los argumentos no se mueven ni se copian porque no es necesario transferirlos a otro hilo de ejecución (tal llamada acall_once
se conoce como activa).
- Si esa invocación lanza una excepción, se propaga al llamante de
call_once
, y la bandera no se invierte para que se intente realizar otra llamada (tal llamada acall_once
se conoce como excepcional). - Si esa invocación retorna/regresa normalmente (tal llamada a
call_once
se conoce como retornante), la bandera se invierte, y se garantiza que todas las demás llamadas acall_once
con la misma bandera son pasivas.
- Si esa invocación lanza una excepción, se propaga al llamante de
Todas las llamadas activas en la misma bandera, flag
, forman un solo orden total que consiste en cero o más llamadas excepcionales, seguidas de una llamada retornante. El final de cada llamada activa se sincroniza-con la siguiente llamada activa en ese orden.
El retorno/regreso de la llamada retornante se sincroniza-con los retornos de todas las llamadas pasivas en la misma bandera, flag
: esto significa que se garantiza que todas las llamadas concurrentes a call_once
observan cualquier efecto secundario producido por la llamada activa, sin sincronización adicional.
Contenido |
[editar] Parámetros
flag | - | Un objeto para el cual se ejecuta exactamente una función. |
f | - | Callable Objeto a invocar. |
args... | - | Argumentos a pasar a la función. |
[editar] Valor de retorno
(Ninguno)
[editar] Excepciones
- std::system_error Si cualquier condición impide que las llamadas a
call_once
se ejecuten como se especifica. - Cualquier excepción lanzada por
f
.
[editar] Notas
Si llamadas concurrentes a call_once
pasan diferentes funciones f
, no se especifica cuál f
se llamará. La función seleccionada se ejecuta en el mismo hilo que la invocación call_once
a la que se pasó.
Se garantiza que la inicialización de variables locales estáticas en una función ocurre solamente una vez incluso cuando se llama desde varios hilos, y puede ser más eficiente que el código equivalente que usa std::call_once
.
El equivalente POSIX de esta función es pthread_once.
[editar] Ejemplo
#include <iostream> #include <thread> #include <mutex> std::once_flag flag1, flag2; void una_vez_sencillo() { std::call_once(flag1, [](){ std::cout << "Ejemplo sencillo: llamado una vez\n"; }); } void funcion_que_puede_lanzar(bool lanzar) { if (lanzar) { // esto puede aparecer más de una vez std::cout << "lanzar: call_once lo intentará de nuevo\n"; throw std::exception(); } // garantizado una vez std::cout << "No se lanzó, call_once no lo intentará de nuevo\n"; } void hacer_una_vez(bool lanzar) { try { std::call_once(flag2, funcion_que_puede_lanzar, lanzar); } catch (...) { } } int main() { std::thread st1(una_vez_sencillo); std::thread st2(una_vez_sencillo); std::thread st3(una_vez_sencillo); std::thread st4(una_vez_sencillo); st1.join(); st2.join(); st3.join(); st4.join(); std::thread t1(hacer_una_vez, true); std::thread t2(hacer_una_vez, true); std::thread t3(hacer_una_vez, false); std::thread t4(hacer_una_vez, true); t1.join(); t2.join(); t3.join(); t4.join(); }
Posible salida:
Ejemplo sencillo: llamado una vez lanzar: call_once lo intentará de nuevo lanzar: call_once lo intentará de nuevo No se lanzó, call_once no lo intentará de nuevo
[editar] Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
---|---|---|---|
LWG 2442 | C++11 | Los argumentos se copian y/o mueven antes de la invocación. | No se realiza copia/movimiento. |
[editar] Véase también
(C++11) |
Objeto auxiliar para asegurarse que call_once invoque la función una sola vez. (clase) |
Documentación de C para call_once
|