#include <stdio.h>␍␊ |
#include <time.h>␍␊ |
#include <stdlib.h>␍␊ |
#include <windows.h>␍␊ |
␍␊ |
#define BUFFER_SIZE 10␍␊ |
␍␊ |
#if !defined(true) && !defined(false)␍␊ |
␉#define true 1␍␊ |
␉#define false 0␍␊ |
#endif␍␊ |
␍␊ |
volatile int counter = -1;␍␊ |
volatile int buffer[BUFFER_SIZE];␍␊ |
␍␊ |
volatile int turn;␍␊ |
volatile int flag[2];␍␊ |
␍␊ |
DWORD WINAPI produce(void* data) {␍␊ |
␉srand (time(NULL));␍␊ |
␉while (true)␍␊ |
␉{␍␊ |
␉␉flag[0] = true;␍␊ |
␉␉turn = 1;␍␊ |
␉␉//while (counter == BUFFER_SIZE - 1); // make sure the buffer doesn't overflow␍␊ |
␉␉while (flag[1] && turn == 1);␍␊ |
␉␉if (counter == BUFFER_SIZE - 1)␍␊ |
␉␉{␍␊ |
␉␉␉continue;␍␊ |
␉␉␉flag[0] = false;␍␊ |
␉␉}␍␊ |
␉␉␍␊ |
␉␉␍␊ |
␉␉buffer[counter + 1] = rand() % 20 + 1; // yes I know rand is not thread safe - I just need a way to demonstrate a producing/consuming problem - using the same number doesn't help.␍␊ |
␉␉printf("PRODUCER value = %i counter = %i\n", buffer[counter + 1], counter + 1);␍␊ |
␉␉counter++;␍␊ |
␉␉flag[0] = false;␍␊ |
␍␊ |
␉}␍␊ |
}␍␊ |
␍␊ |
DWORD WINAPI consume(void* data) {␍␊ |
␉while(true)␍␊ |
␉{␍␊ |
␉␉flag[1] = true;␍␊ |
␉␉turn = 0;␍␊ |
␉␉//while (counter == -1); // make sure there is content to consume␍␊ |
␉␉while (flag[0] && turn == 0);␍␊ |
␉␉if (counter == -1) // producer hasn't produced␍␊ |
␉␉{␍␊ |
␉␉␉flag[1] = false;␍␊ |
␉␉␉continue;␍␊ |
␉␉}␍␊ |
␉␉if (buffer[counter] == 0)␍␊ |
␉␉{␍␊ |
␉␉␉printf("%i\n", buffer[counter]);␍␊ |
␉␉␉printf("Attempting to consume an element that was already consumed counter = %i\n", counter);␍␊ |
␉␉␉exit(1);␍␊ |
␉␉}␍␊ |
␉␉printf("CONSUMER value = %i counter = %i\n", buffer[counter], counter);␍␊ |
␉␉counter--;␍␊ |
␉␉buffer[counter] = 0;␍␊ |
␉␉flag[1] = false;␍␊ |
␉}␍␊ |
}␍␊ |
␍␊ |
int main() {␍␊ |
␉int i;␍␊ |
␉HANDLE thread1, thread2;␍␊ |
␉for(i = 0; i < BUFFER_SIZE; i++)␍␊ |
␉␉buffer[i] = -1;␍␊ |
␉flag[0] = true;␍␊ |
␉flag[1] = true;␍␊ |
␉␍␊ |
␉thread1 = CreateThread(NULL, 0, produce, NULL, 0, NULL);␍␊ |
␉thread2 = CreateThread(NULL, 0, consume, NULL, 0, NULL);␍␊ |
␉WaitForSingleObject(thread1, 50);␍␊ |
␉WaitForSingleObject(thread2, 50);␍␊ |
} |