Inicializaciones puntuales
Algunas bibliotecas C están diseñadas para la inicialización dinámica, en la que la inicialización global de la biblioteca se realiza cuando se llama al primer procedimiento de la biblioteca.
En un programa de una sola hebra, normalmente se implementa utilizando una variable estática cuyo valor se comprueba al entrar en cada rutina, como en el fragmento de código siguiente:
static int isInitialized = 0;
extern void Initialize();
int function()
{
if (isInitialized == 0) {
Initialize();
isInitialized = 1;
}
...
}Para la inicialización de biblioteca dinámica en un programa multihebra, un distintivo de inicialización simple no es suficiente. Este distintivo debe estar protegido contra la modificación por varias hebras que llaman simultáneamente a una función de biblioteca. La protección del distintivo requiere el uso de un mutex; sin embargo, los mutexes deben inicializarse antes de que se utilicen. Asegurarse de que el mútex sólo se inicializa una vez requiere una solución recursiva a este problema.
Para mantener la misma estructura en un programa multihebra, utilice la subrutina pthread_once . De lo contrario, la inicialización de la biblioteca debe realizarse mediante una llamada explícita a una función de inicialización exportada de la biblioteca antes de cualquier uso de la biblioteca. La subrutina pthread_once también proporciona una alternativa para inicializar mutexes y variables de condición.
Lea lo siguiente para obtener más información sobre las inicializaciones únicas:
Objeto de inicialización único
La exclusividad de la inicialización se garantiza mediante el objeto de inicialización de una sola vez. Es una variable que tiene el tipo de datos pthread_once_t . En AIX® y en la mayoría de las otras implementaciones de la librería threads, el tipo de dato pthread_once_t es una estructura.
Un objeto de inicialización de una sola vez suele ser una variable global. Debe inicializarse con la macro PTHREAD_ONCE_INIT , como en el ejemplo siguiente:
static pthread_once_t once_block = PTHREAD_ONCE_INIT;La inicialización también se puede realizar en la hebra inicial o en cualquier otra hebra. Se pueden utilizar varios objetos de inicialización de una sola vez en el mismo programa. El único requisito es que el objeto de inicialización de una sola vez se inicialice con la macro.
Rutina de inicialización única
void init_routine();La subrutina pthread_once no proporciona un punto de cancelación. Sin embargo, la rutina de inicialización puede proporcionar puntos de cancelación y, si la cancelabilidad está habilitada, la primera hebra que llama a la subrutina pthread_once puede cancelarse durante la ejecución de la rutina de inicialización. En este caso, la rutina no se considera ejecutada, y la siguiente llamada a la subrutina pthread_once provocaría la recuperación de la rutina de inicialización.
Se recomienda utilizar manejadores de limpieza en rutinas de inicialización de una sola vez, especialmente cuando se realizan operaciones no idempotentes, como abrir un archivo, bloquear un mutex o asignar memoria.
void
init_routine();) se escribiría de la forma siguiente:static pthread_once_t once_block = PTHREAD_ONCE_INIT;
extern void Initialize();
int function()
{
pthread_once(&once_block, Initialize);
...
}