Чтение онлайн

на главную - закладки

Жанры

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

под ключом thread_log_key. */

 pthread_setspecific(thread_log_key, thread_log);

 write_to_thread_log("Thread starting.");

 /* Далее идет основное тело потока... */

 return NULL;

}

int main {

 int i;

 pthread_t threads[5];

 /* Создание ключа,
который будет связывать указатели

журнальных файлов с областью потоковых данных. Функция

close_thread_log закрывает все файлы. */

 pthread_key_create(&thread_log_key, close_thread_log);

 /* Создание потоков. */

 for (i = 0; i < 5; ++i)

pthread_create(&(threads[i]), NULL, thread_function, NULL);

 /* Ожидание завершения всех потоков. */

 for (i = 0; i < 5; ++i)

pthread_join(threads[i], NULL);

 return 0;

}

Обратите внимание на то, что в функции

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

4.3.1. Обработчики очистки

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

Обработчик очистки вызывается при завершении потока. Он принимает один аргумент типа

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

Обработчик очистки — это временная мера, требуемая только тогда, когда поток завершается или отменяется, не закончив выполнять определенный участок кода. При нормальных обстоятельствах ресурс должен удаляться явно.

Для регистрации обработчика следует вызвать функцию

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

В листинге 4.8 показан фрагмент программы, в котором обработчик очистки применяется для удаления динамического буфера при завершении потока.

Листинг 4.8. (cleanup.c) Фрагмент программы, содержащий обработчик очистки потока

#include <malloc.h>

#include <pthread.h>

/*
Выделение временного буфера. */

void* allocate_buffer(size_t size) {

 return malloc(size);

}

/* Удаление временного буфера. */

void deallocate_buffer(void* buffer) {

 free(buffer);

}

void do_some_work {

 /* Выделение временного буфера. */

 void* temp_buffer = allocate_buffer(1024);

 /* Регистрация обработчика очистки для данного буфера. Этот

обработчик будет удалять буфер при завершении или отмене

потока. */

 pthread_cleanup_push(deallocate_buffer, temp_buffer);

 /* Выполнение других действий... */

 /* Отмена регистрации обработчика. Поскольку функции передается

ненулевой аргумент, она выполняет очистку, вызывая функцию

deallocate_buffer. */

 pthread_cleanup_pop(1);

}

В данном случае функции

pthread_cleanup_pop
передается ненулевой аргумент, поэтому функция очистки
deallocate_buffer
вызывается автоматически. В данном простейшем случае можно было в качестве обработчика непосредственно использовать стандартную библиотечную функцию
free
.

4.3.2. Очистка потоковых данных в C++

Программисты, работающие на C++, привыкли к тому, что очистку за них делают деструкторы объектов. Когда объект выходит за пределы своей области видимости, либо по достижении конца блока, либо вследствие возникновения исключительной ситуации, среда выполнения C++ гарантирует вызов деструкторов для тех автоматических переменных, у которых они есть. Это удобный механизм очистки, работающий независимо от того, как осуществляется выход из конкретного программного блока.

Тем не менее, если поток вызывает функцию

pthread_exit
, среда выполнения C++ не может гарантировать вызов деструкторов для всех автоматических переменных, находящихся в стеке потока. Чтобы этого добиться, нужно вызвать функцию
pthread_exit
в рамках конструкции
try/catch
, охватывающей все тело потоковой функции. При этом перехватывается специальное исключение
ThreadExitException
.

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

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

Поделиться:
Популярные книги

Черный маг императора 3

Герда Александр
3. Черный маг императора
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора 3

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

Пипец Котенку! 3

Майерс Александр
3. РОС: Пипец Котенку!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Пипец Котенку! 3

Разбуди меня

Рам Янка
7. Серьёзные мальчики в форме
Любовные романы:
современные любовные романы
остросюжетные любовные романы
5.00
рейтинг книги
Разбуди меня

Боги, пиво и дурак. Том 6

Горина Юлия Николаевна
6. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 6

Болотник 2

Панченко Андрей Алексеевич
2. Болотник
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Болотник 2

Ты всё ещё моя

Тодорова Елена
4. Под запретом
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Ты всё ещё моя

S-T-I-K-S. Пройти через туман

Елисеев Алексей Станиславович
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
7.00
рейтинг книги
S-T-I-K-S. Пройти через туман

Имя нам Легион. Том 4

Дорничев Дмитрий
4. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 4

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Я князь. Книга XVIII

Дрейк Сириус
18. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я князь. Книга XVIII

Королевская Академия Магии. Неестественный Отбор

Самсонова Наталья
Любовные романы:
любовно-фантастические романы
8.22
рейтинг книги
Королевская Академия Магии. Неестественный Отбор

Последняя Арена 6

Греков Сергей
6. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 6

Жребий некроманта. Надежда рода

Решетов Евгений Валерьевич
1. Жребий некроманта
Фантастика:
фэнтези
попаданцы
6.50
рейтинг книги
Жребий некроманта. Надежда рода