-
Notifications
You must be signed in to change notification settings - Fork 1
06_ext
Perestoronin Pavel edited this page Jan 11, 2021
·
1 revision
HANDLE mutex;
HANDLE can_read;
HANDLE can_write;
LONG waiting_writers = 0;
LONG waiting_readers = 0;
LONG active_readers = 0;
bool active_writer = false;
int value = 0;
void start_read(void) {
InterlockedIncrement(&waiting_readers);
if (active_writer || (WaitForSingleObject(can_write, 0) == WAIT_OBJECT_0 && waiting_writers))
WaitForSingleObject(can_read, INFINITE);
WaitForSingleObject(mutex, INFINITE);
InterlockedDecrement(&waiting_readers);
InterlockedIncrement(&active_readers);
SetEvent(can_read);
ReleaseMutex(mutex);
}
void stop_read(void) {
InterlockedDecrement(&active_readers);
if (active_readers == 0) {
ResetEvent(can_read);
SetEvent(can_write);
}
}
DWORD WINAPI run_reader(CONST LPVOID lpParams) {
int index = (int)lpParams;
int sleep_time;
srand(time(NULL) + index);
for (size_t i = 0; i < 7; i++) {
sleep_time = 300 + rand() % 4000;
Sleep(sleep_time);
start_read();
printf(" Reader #%ld read: %5ld (slept %4d ms)\n", index, value, sleep_time);
stop_read();
}
return 0;
}
void start_write(void) {
InterlockedIncrement(&waiting_writers);
if (active_writer || active_readers > 0)
WaitForSingleObject(can_write, INFINITE);
InterlockedDecrement(&waiting_writers);
active_writer = true;
}
void stop_write(void) {
active_writer = false;
if (waiting_readers)
SetEvent(can_read);
else
SetEvent(can_write);
}
DWORD WINAPI run_writer(CONST LPVOID lpParams) {
int index = (int)lpParams;
int sleep_time;
srand(time(NULL) + index + 5);
for (int i = 0; i < 8; ++i) {
sleep_time = 300 + rand() % 4000;
Sleep(sleep_time);
start_write();
++value;
printf(" Writer #%ld write: %5ld (slept %4d ms)\n", index, value, sleep_time);
stop_write();
}
return 0;
}
int main(void) {
setbuf(stdout, NULL);
HANDLE readers_threads[5];
HANDLE writers_threads[3];
if ((mutex = CreateMutex(NULL, FALSE, NULL)) == NULL) {
perror("Failed call of CreateMutex");
return -1;
}
if ((can_read = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL
|| (can_write = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
perror("Failed call of CreateEvent");
return -1;
}
for (int i = 0; i < 5; ++i)
if ((readers_threads[i] = CreateThread(NULL, 0, run_reader, (LPVOID)i, 0, NULL)) == NULL) {
perror("Failed call of CreateThread");
return -1;
}
for (int i = 0; i < 3; i++)
if ((writers_threads[i] = CreateThread(NULL, 0, run_writer, (LPVOID)i, 0, NULL)) == NULL) {
perror("Failed call of CreateThread");
return -1;
}
WaitForMultipleObjects(5, readers_threads, TRUE, INFINITE);
WaitForMultipleObjects(3, writers_threads, TRUE, INFINITE);
CloseHandle(mutex);
CloseHandle(can_read);
CloseHandle(can_write);
return 0;
}