[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]

Программирование: Разработка и отладка программ


Разовая инициализация

Некоторые библиотеки языка C могут инициализироваться динамически. Это означает, что глобальная инициализация библиотеки выполняется при первом вызове процедуры из нее. В программах с одной нитью это реализуется с помощью статической переменной, значение которой проверяется при запуске каждой процедуры, как показано в приведенном ниже фрагменте кода:

static int isInitialized = 0;
extern void Initialize();
 
int function()
{
        if (isInitialized == 0) {
                Initialize();
                isInitialized = 1;
        }
        ...
}

В программах с несколькими нитями, в которых выполняется динамическая инициализация библиотек, простого флага инициализации недостаточно. Этот флаг должен быть защищен от изменения при одновременном вызове функции библиотеки несколькими нитями. Для защиты флага требуется применять механизм взаимных блокировок (семафоров), однако и эти семафоры необходимо предварительно инициализировать. Таким образом, требование разовой инициализации семафоров возвращает к исходной проблеме.

Для того чтобы сохранить прежнюю структуру в программах с несколькими нитями, в библиотеке нитей предусмотрена новая функция pthread_once. Если такой вариант вас не устраивает, вы можете выполнять инициализацию явно, вызывая перед каждым применением библиотеки экспортированную функцию инициализации. Эта функцию можно применять вместо взаимных блокировок и условных переменных.

Дополнительные сведения о разовой инициализации можно найти в следующих разделах:

Объект разовой инициализации

Однократность инициализации гарантируется специальным объектом, называемым объектом инициализации. Этот объект представляет собой переменную типа pthread_once_t. В AIX и большинстве других реализаций библиотеки нитей тип данных pthread_once_t является структурой.

Объект разовой инициализации обычно является глобальной переменной. Эта переменная инициализируется макрокомандой PTHREAD_ONCE_INIT, как показано в следующем примере:

static pthread_once_t once_block = PTHREAD_ONCE_INIT;

Инициализация может быть выполнена как в начальной, так и в любой другой нити. В одной программе могут встречаться несколько объектов разовой инициализации. К ним предъявляется только одно требование - они должны быть инициализированы макрокомандой.

Процедура разовой инициализации

При первом вызове функция pthread_once вызывает процедуру инициализации, связанную с указанным объектом разовой инициализации. При всех последующих вызовах она не выполняет никаких действий. С каждым объектом разовой инициализации должна быть связана только одна процедура инициализации. Прототип процедуры инициализации должен выглядеть следующим образом:

void init_routine();

Функция pthread_once не содержит точек завершения. Но процедура инициализации может включать точки завершения, и если завершение разрешено, то первую нить, вызвавшую функцию pthread_once, можно прервать во время выполнения процедуры инициализации. В этом случае процедура не будет считаться выполненной, и при следующем вызове функции pthread_once процедура инициализации будет вызвана повторно.

При создании функций разовой инициализации, особенно выполняющих неидемпотентные операции, такие как открытие файла, установка взаимной блокировки или выделение памяти, рекомендуется регистрировать функции очистки. Более подробная информация приведена в разделе Процедуры очистки.

Процедуры разовой инициализации могут применяться для инициализации взаимных блокировок или условных переменных, а также для выполнения динамической инициализации. В случае библиотеки, применяемой несколькими нитями, приведенный выше фрагмент кода будет выглядеть следующим образом:

static pthread_once_t once_block = PTHREAD_ONCE_INIT;
extern void Initialize();
 
int function()
{
        pthread_once(&once_block, Initialize);
        ...
}

Связанная информация

Рекомендации по созданию программ с нитями

Дополнительные функции работы с нитями

Данные нитей

Расширенные атрибуты

Создание сложных объектов синхронизации

Список дополнительных функций для работы с нитями


[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]