std:: call_once
|
Definido en el encabezado
<mutex>
|
||
|
template
<
class
Callable,
class
...
Args
>
void call_once ( std:: once_flag & flag, Callable && f, Args && ... args ) ; |
(desde C++11) | |
Ejecuta el objeto Callable f exactamente una vez, incluso si se llama concurrentemente desde varios hilos.
En detalle:
-
Si, para el momento en que se llama a
std::call_once, flag indica que f ya fue llamado,std::call_onceretorna inmediatamente (dicha llamada astd::call_oncese conoce como pasiva ).
-
En caso contrario,
std::call_oncellama a INVOKE ( std:: forward < Callable > ( f ) , std:: forward < Args > ( args ) ... ) . A diferencia del constructor de std::thread o de std::async , los argumentos no se mueven ni copian porque no necesitan transferirse a otro hilo de ejecución (dicha llamada astd::call_oncese conoce como activa ).
-
-
Si esa invocación lanza una excepción, se propaga al llamador de
std::call_once, y flag no se activa para que se intente otra llamada (dicha llamada astd::call_oncese conoce como excepcional ). -
Si esa invocación retorna normalmente (dicha llamada a
std::call_oncese conoce como de retorno ), flag se activa, y todas las demás llamadas astd::call_oncecon el mismo flag están garantizadas de ser pasivas .
-
Si esa invocación lanza una excepción, se propaga al llamador de
Todas las activas llamadas en la misma flag forman un único orden total que consiste en cero o más excepcionales llamadas, seguidas por una retornante llamada. El final de cada activa llamada sincroniza-con la siguiente activa llamada en ese orden.
El retorno de la llamada
activa
sincroniza-con los retornos de todas las llamadas
pasivas
en el mismo
flag
: esto significa que todas las llamadas concurrentes a
std::call_once
están garantizadas de observar cualquier efecto secundario realizado por la llamada
activa
, sin sincronización adicional.
Contenidos |
Parámetros
| flag | - | un objeto para el cual se ejecuta exactamente una función |
| f | - | Callable objeto a invocar |
| args... | - | argumentos para pasar a la función |
Valor de retorno
(ninguno)
Excepciones
-
std::system_error
si alguna condición impide que las llamadas a
std::call_oncese ejecuten según lo especificado. - Cualquier excepción lanzada por f .
Notas
Si llamadas concurrentes a
std::call_once
pasan diferentes funciones
f
, no está especificado cuál
f
será ejecutada. La función seleccionada se ejecuta en el mismo hilo que la invocación de
std::call_once
a la que fue pasada.
La inicialización de
variables estáticas locales de función
está garantizada que ocurra solo una vez incluso cuando se llama desde múltiples hilos, y puede ser más eficiente que el código equivalente usando
std::call_once
.
El equivalente POSIX de esta función es
pthread_once
.
Ejemplo
#include <iostream> #include <mutex> #include <thread> std::once_flag flag1, flag2; void simple_do_once() { std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; }); } void may_throw_function(bool do_throw) { if (do_throw) { std::cout << "Throw: call_once will retry\n"; // esto puede aparecer más de una vez throw std::exception(); } std::cout << "Did not throw, call_once will not attempt again\n"; // garantizado una vez } void do_once(bool do_throw) { try { std::call_once(flag2, may_throw_function, do_throw); } catch (...) {} } int main() { std::thread st1(simple_do_once); std::thread st2(simple_do_once); std::thread st3(simple_do_once); std::thread st4(simple_do_once); st1.join(); st2.join(); st3.join(); st4.join(); std::thread t1(do_once, true); std::thread t2(do_once, true); std::thread t3(do_once, false); std::thread t4(do_once, true); t1.join(); t2.join(); t3.join(); t4.join(); }
Salida posible:
Simple example: called once Throw: call_once will retry Throw: call_once will retry Throw: call_once will retry Did not throw, call_once will not attempt again
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2080 | C++11 |
std::invalid_argument
sería lanzado si
f
es inválido,
pero el escenario donde f se invalida no está especificado |
eliminada esta condición de error |
| LWG 2442 | C++11 | los argumentos eran copiados y/o movidos antes de la invocación | no se realiza copia/traslado |
Véase también
|
(C++11)
|
objeto auxiliar para garantizar que
call_once
invoque la función solo una vez
(clase) |
|
Documentación C
para
call_once
|
|