В конечном счете, поскольку необходимость обеспечивать обработку большого числа исключительных ситуаций при использовании нового сигнала с существующими сигнальными функциями может неоправданно усложнить (даже запутать) процесс отмены потока, было решено сделать выбор в пользу специальной функции, которая устраняет эту проблему. Такая функция была тщательно разработана, причем так, что любая реализация могла бы обеспечить «безоговорочное» выполнение процедуры отмены «поверх» каких бы то ни было сигналов. Наличие специальной функции отмены потока также означает, что реализации не обязаны обеспечивать процедуру отмены с помощью сигналов.
Будущие направления
Отсутствуют.
Смотри также
pthread_exit (), pthread_cond_timedwait (), pthread_join (), pthread_setcancelstate (), то м Base D e finitions стандарта IEEE Std 1003.1-2001, .
Последовательность внесения изменений
Функция впервые реализована в выпуске Issue 5. Включена для согласования с расширение м POSIX Threads Ext e nsion.
Issue 6
Функция pthread_cancel () от м ечена как часть опции Thr e ads.
pthread_cleanup_pop, pthread_cleanup_push
Имя
pthread_cleanup_pop, pthread_cleanup_push— функции создания обработчиков запроса об от м ене потоков.
Синопсис
THR
#include
void pthread_cleanup_pop (int execute);
void pthread_cleanup_push (void (* routine) (void*),void *arg);
Описание
Функция pthread_cleanup_pop () используется для извлечения функции, расположенной в вершине стека вызываю щ его потока, предназначенного дл я выполнения подготовительных действий по аннулированию потока, и ее вызова (если пара м етр execute не равен нулю).
Функция pthread_cleanup_push() позволяет поместить в стек вызывающего потока заданную функцию обработчика routine, предназначенного для выполнения подготовительных действий по аннулированию потока. Этот обработчик будет извлечен из соответствующего стека и вызван с аргументом arg при наличии следующих условий:
• поток существует (т.е. он вызывает функцию pthread_exit ());
• поток действует в соответствии с запросом отмены;
• поток вызывает функцию pthread_cleanup_pop() с ненулевым значением аргумента execute.
Эти функции можно реализовать как макросы. Приложение должно гарантировать, что они имеют форму инструкций и используются попарно в пределах одного и того же лексического контекста (чтобы макрос pthread_cleanup_push () раскрывался в список лексем, начинающийся лексемой '{', а макрос pthread_cleanup_pop() раскрывался в список лексем, завершающийся соответствующей лексемой '}').
Результат вызова функции longjmp() или siglongjmp() не определен, ec-ли имели место обращения к функции pthread_cleanup_push() или pthread_cleanup_pop() без соответствующего «парного» вызова по причине заполнения буфера переходов. Результат вызова функции longjmp () или siglongjmp() из обработчика, предназначенного для выполнения подготовительных действий по аннулированию потока, также не определен.
Возвращаемые значения
Функции pthread_cleanup_push() и hread_cleanup_pop() не возвра щ ают никакого значения.
Ошибки
Ошибки не определены.
Эти функции не возвращают код ошибки [EINTR].
Примеры
Следующий код представляет собой пример использования примитивов потока для реализации блокировки чтения-записи (с приоритетом для записи) с возможностью отмены.
typedef struct {
pthread_mutex_t lock; pthread_cond_t rcond, wcond;
int lock_count;
/* lock_count < 0 .. Удерживается записывающим потоком. */ /* lock_count > 0 .. Удерживается lock_count считывающими * потоками. */
/* lock_count = 0 .. Ничем не удерживается. */ int waiting_writers; /* Счетчик ожидающих записывающих
* потоков. */
} rwlock;
void
waiting_reader_cleanup (void, *arg) {
rwlock *1;
1 = (rwlock *) arg;
pthread_mutex_unlock (&l->lock);
}
void
lock_for_read (rwlock *1) {
pthread_mutex_lock (&l->lock);
pthread_cleanup_push (waiting_reader_cleanup, 1) ;
while ((l->lock_count < 0) && (l->waiting_writers ! = 0))
pthread_cond_wait (&l->rcond, &l->lock);
l->lock_count++;
/*
* Обратите внимание на то, что функция pthread_cleanup_pop()
* выполняет здесь фyнкциюwaiting_reader_cleanup(). */
pthread_cleanup_pop(l); }
void
release_read_lock (rwlock *1) {
pthread_mutex_lock (&l->lock); if (--l->lock_count == 0) pthread_cond_signal (&l->wcond); pthread_mutex_unlock (1);
void
waiting_writer_cleanup (void *arg) {
rwlock *1;
1 = (rwlock *) arg;
if ((—l->waiting_writers == О) && (l->lock_count >= 0)) { /*
* Это происходит только в случае отмены потока. */
pthread_cond_broadcast (&l->wcond);
Читать дальше