Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform | страница 53
>consumer() {
> while (1) {
> pthread_sleepon_lock();
> while (!data_ready) {
> // WAIT
> }
> // Обработать данные
> data_ready = 0;
> pthread_sleepon_unlock();
> }
>}
Здесь мы добавили «потребителю» установку и снятие блокировки. Это означает, что потребитель может теперь надежно проверять флаг data_ready, не опасаясь гонок, а также надежно его устанавливать.
Великолепно! А как насчет собственно процесса ожидания? Как мы и предполагали ранее, там действительно применяется вызов функции pthread_sleepon_wait(). Вот второй while-цикл:
>while (!data_ready) {
> pthread_sleepon_wait(&data_ready);
>}
Функция pthread_sleepon_wait() в действительности выполняет три действия:
1. Разблокирует мутекс библиотеки ждущих блокировок.
2. Выполняет собственно операцию ожидания.
3. Снова блокирует мутекс библиотеки ждущих блокировок.
Причина обязательной разблокировки/блокировки мутекса библиотеки проста: поскольку суть мутекса состоит в обеспечении взаимного исключения доступа к флагу data_ready, мы хотим запретить потоку-«производителю» изменять флаг data_ready, пока мы его проверяем. Но если мы не разблокируем флаг впоследствии, то поток-«производитель» не сможет его установить, чтобы сообщить нам о доступности данных! Операция повторной блокировки выполняется автоматически исключительно для удобства, чтобы вызвавший функцию pthread_sleepon_wait() поток не беспокоился о состоянии блокировки после «пробуждения».
Давайте перейдем теперь к потоку-«производителю» и рассмотрим, как он использует библиотеку ждущих блокировок. Вот его полная реализация:
>producer() {
> while (1) {
> // Ждать прерывания от оборудования...
> pthread_sleepon_lock();
> data_ready = 1;
> pthread_sleepon_signal(&data_ready);
> pthread_sleepon_unlock();
> }
>}
Как вы видите, поток-«производитель» также блокирует мутекс, чтобы получить монопольный доступ к флагу data_ready перед его установкой.
Давайте рассмотрим происходящее в подробностях. Определим состояния «потребителя» и «производителя» следующим образом:
Состояние | Означает |
---|---|
CONDVAR | ожидание соответствующей ждущей блокировке условной переменной |
MUTEX | ожидание мутекса |
READY | состояние готовности, т.е., готов выполняться или уже выполняется |
INTERRUPT | ожидание прерывания от аппаратных средств |
Действие | Владелец мутекса | Состояние «потребителя» |
---|