Рассмотрим следующий поток программы:
pthread_rwlock_rdlock( &mylock);
... compute a lot, maybe be the target of a pthread_cancel() ...
pthread_rwlock_unlock( &mylock);
, который собирается оставить блокировку в состоянии rdlock, если поток отменен.
Похоже, что "правильное", что нужно сделать, это использовать pthread_cleanup_push () и pthread_cleanup_pop () и выполнить разблокировку внутри моей функции очистки, но, похоже, нет правильного порядка для вызовов функции:
void my_cleanup(void *arg) { pthread_rwlock_unlock(&mylock); }
...
pthread_cleanup_push( my_cleanup, 0);
/* A */
pthread_rwlock_rdlock( &mylock);
... compute a lot, maybe be the target of a pthread_cancel() ...
pthread_cleanup_pop( 1);
... это выглядит почти правильно, за исключением того, что если pthread_cancel () попадет в "A", очистка разблокирует mylock, который еще не заблокирован, что приводит к неопределенному поведению.
Полный ответ может быть следующим:
void my_cleanup(void *arg) { pthread_rwlock_unlock(&mylock); }
...
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate);
pthread_cleanup_push( my_cleanup, 0);
pthread_rwlock_rdlock( &mylock);
pthread_setcancelstate( oldstate, 0);
... compute a lot, maybe be the target of a pthread_cancel() ...
pthread_cleanup_pop( 1);
, но в этот момент мне кажется, что я оборачиваю некоторые хорошо определенные примитивы в бинты.
Так что есть ли лучшеидиома для этого?