Espacios de nombres
Variantes
Acciones

std::call_once

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
Gestión genérica de bloqueo
(C++11)
(C++11)
(C++11)
call_once
(C++11)
Variables de condición
(C++11)
Semáforos
Pestillos y barreras
(C++20)
(C++20)
Futuros
(C++11)
(C++11)
(C++11)
Recuperación segura
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 <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 que f ya se llamó, call_once regresa de inmediato (tal llamada a call_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 a call_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 a call_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 a call_once con la misma bandera son pasivas.

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 vezstd::cout<<"lanzar: call_once lo intentará de nuevo\n";throwstd::exception();}// garantizado una vezstd::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)[editar]
Documentación de C para call_once
close