tprintf(_T("Такая команда отсутствует. Повторите попытку.\n"));
}
}
return 0;
}
void MessageFill(MSG_BLOCK *mblock) {
/* Заполнить буфер сообщения содержимым, включая контрольную сумму и отметку времени. */
DWORD i;
mblock->checksum = 0;
for (i = 0; i < DATA_SIZE; i++) {
mblock->data[i] = rand;
mblock->checksum ^= mblock->data[i];
}
mblock->timestamp = time(NULL);
return;
}
void MessageDisplay(MSG_BLOCK *mblock) {
/*
Отобразить буфер сообщения, отметку времени и контрольную сумму. */
DWORD i, tcheck = 0;
for (i = 0; i < DATA_SIZE; i++) tcheck ^= mblock->data[i];
_tprintf(_T("\nВремя генерации сообщения № %d: %s"), mblock->sequence, _tctime(&(mblock->timestamp)));
_tprintf(_T("Первая и последняя записи: %х %х\n"), mblock->data[0], mblock->data[DATA_SIZE – 1]);
if (tcheck == mblock->checksum) _tprintf(_T("УСПЕШНАЯ ОБРАБОТКА –>Контрольная сумма совпадает.\n"));
else tprintf(_T("СБОЙ –>Несовпадение контрольной суммы. Сообщение запорчено.\n"));
return;
}
Комментарии к примеру простой системы "производитель/потребитель"
Этот пример иллюстрирует некоторые моменты и соглашения, касающиеся программирования, которые будут важны для нас на протяжении этой и последующих глав.
• Объект CRITICAL_SECTION является частью объекта (блока сообщения), защиту которого он обеспечивает.
• Каждый доступ к сообщению осуществляется на критическом участке кода.
• Типом переменных, доступ к которым осуществляется разными потоками, является volatile.
• Использование обработчиков завершения гарантирует, что объекты CS будут обязательно освобождены. Хотя в данном случае эта методика и не является для нас существенной, она дополнительно гарантирует, что вызов функции LeaveCriticalSection не будет случайно опущен впоследствии при изменении кода программы. Имейте также в виду, что обработчик завершения ограничен использованием средств С, и его не следует использовать совместно с C++.
• Функции MessageFill и MessageDisplay вызываются лишь на критических участках кода и используют для нужд своих вычислений не глобальную, а локальную память. Кстати, обе они будут применяться и в последующих примерах, но их листинги больше приводиться не будут.
• Не существует удобного способа, при помощи которого поток производителя мог бы известить поток потребителя о наличии нового сообщения, и поэтому поток потребителя должен просто ожидать, пока не будет установлен флаг готовности, который используется для индикации появления нового сообщения. Устранить этот недостаток нам помогут объекты событий ядра.
• Одним из инвариантных свойств, которые гарантируются этой программой, является то, что контрольная сумма блока сообщения будет всегда корректной вне критических участков кода. Другим инвариантным свойством является следующее: