Программа 8.1 демонстрирует, насколько полезными могут быть объекты CS.
Пример: простая система "производитель/потребитель"
Программа 8.1 иллюстрирует, насколько полезными могут быть объекты CS. Кроме того, эта программа демонстрирует, как создаются защищенные структуры данных для хранения состояний объектов, и знакомит с понятием
Рис. 8.2.
Разделение общей памяти синхронизированными потокамиОписание задачи приводится ниже.
• Имеются два потока,
• Производитель периодически создает сообщения, содержащие таблицу чисел, например, таблицу биржевых котировок, которая периодически обновляется.
• По требованию пользователя потребитель отображает текущие данные. Требуется, чтобы отображаемые данные представляли собой
• Данные не должны отображаться в те промежутки времени, когда они обновляются производителем; устаревшие данные также не должны отображаться. Обратите внимание на то, что многие сообщения вообще никогда не используются и, таким образом, "теряются". Этот пример является частным случаем конвейерной модели, в которой данные передаются из одного потока в другой.
• В качестве средства контроля целостности данных производитель вычисляет простую контрольную сумму[28]
данных таблицы, которая далее сравнивается с аналогичной суммой, вычисленной потребителем, дабы удостовериться в том, что данные не были повреждены при их передаче из одного потока в другой. Данные, полученные при обращении к таблице в моменты ее обновления, будут недействительными; использование объектов CS гарантирует, что этого никогда не произойдет. Инвариантом блока сообщения (message block invariant) является корректность контрольной суммы для содержимого текущего сообщения.• Обоими потоками поддерживается статистика суммарного количества отправленных, полученных и утерянных сообщений.
/* Глава 8. simplePC.с */
/* Поддерживает два потока — производителя и потребителя. */
/* Производитель периодически создает буферные данные с контрольными */
/* суммами, или "блоки сообщений", отображаемые потребителем по запросу */
/* пользователя. */
#include "EvryThng.h"
#include
#define DATA_SIZE 256
typedef struct msg_block_tag { /* Блок сообщения. */
volatile DWORD f_ready, f_stop; /* Флаги готовности и прекращения сообщений. */
volatile DWORD sequence; /* Порядковый номер блока сообщения. */
volatile DWORD nCons, nLost;
time_t timestamp;
CRITICAL_SECTION mguard; /* Структура защиты блока сообщения. */
DWORD checksum; /* Контрольная сумма содержимого сообщения. */
DWORD data[DATA_SIZE]; /* Содержимое сообщения. */
} MSG_BLOCK;
/* Одиночный блок, подготовленный к заполнению новым сообщением. */
MSG_BLOCK mblock = { 0, 0, 0, 0, 0 };
DWORD WINAPI produce(void*);
DWORD WINAPI consume(void*);
void MessageFill(MSG_BLOCK*);
void MessageDisplay(MSG_BLOCK*);
DWORD _tmain(DWORD argc, LPTSTR argv[]) {
DWORD Status, ThId;
HANDLE produce h, consume_h;
/* Инициализировать критический участок блока сообщения. */
InitializeCriticalSection (&mblock.mguard);
/* Создать два потока. */
produce_h = (HANDLE)_beginthreadex(NULL, 0, produce, NULL, 0, &ThId);
consume_h = (HANDLE)_beginthreadex (NULL, 0, consume, NULL, 0, &ThId);