Параллельное и распределенное программирование на С++ (Хьюз, Хьюз) - страница 403

Эти функции можно реализовать как макросы. Приложение должно гарантировать, что они имеют форму инструкций и используются попарно в пределах одного и того же лексического контекста (чтобы макрос 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);

>}

>pthread_mutex_unlock (&l->lock);

>}

>void

>lock_for_write (rwlock *1) {

>pthread_mutex_lock (&l->lock),-l->waiting_writers++;

>pthread_cleanup_push (waiting_writer_cleanup, 1); while (l->lock_count ! = О) pthread_cond_wait (&l->wcond, &l->lock); l->lock_count = -1; /*