Синхронизация обедающих философов мьютексами и событием
Пытаюсь решить задачу обедающих философов. Согласно заданию, необходимо использовать и мьютекс, и событие. Основное внимание уделяется состоянию философов, а не вилок. Создавать вспомогательный поток нельзя. Программа является консольной и запускается с 2 аргументами командной строки:phil TOTAL PHIL. Где TOTAL — общее время работы программы (в миллисекундах), PHIL — минимальное время в мс, которое философ может проводить в каком-либо состоянии (есть, размышлять). Философ не должен менять состояние быстрее, чем через PHIL ms. К моменту завершения программы все философы должны быть в состоянии T. Философы не должны менять состояние на E, если программа уже отработала TOTAL ms. Если, например, философ перешел в состояние E в момент 950, а при этом TOTAL=1000 и PHIL=100, то философ имеет возможность завершить "поедание", и поедание завершится в момент 1050. Суммарное время работы программы при этом никогда не должно превысит TOTAL+PHIL ms.
Моя проблема состоит в том, что я не понимаю, как в данной задаче использовать событие.
Мой код на данный момент:
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#define phil_num 5
time_t total;
time_t et_time;
time_t start;
time_t max_time;
volatile int phil_state[phil_num] = { 0 }; //0 - thinking; 1 - eating
volatile int phil_count = 0;
volatile int flag = 1;
HANDLE mutex;
HANDLE event;
HANDLE threads[phil_num];
DWORD WINAPI philosopher(void* param);
bool is_possible(int phil_id);
int get_time(time_t beg_tick);
DWORD WINAPI philosopher(void* param)
{
volatile int idx = ((char*)param - (char*)0) + 1;
while (1)
{
if (get_time(start) >= total)
return 0;
WaitForSingleObject(mutex, INFINITE);
if (is_possible(idx))
{
//printf("thread %d has time %d \n", idx, get_time(start));
if (get_time(start) + et_time > max_time || get_time(start) >= total)
{
//printf("thread %d has finished \n", idx);
ReleaseMutex(mutex);
return 0;
}
phil_count++;
phil_state[idx - 1] = 1;//eat
printf("%d:%d:T->E\n", get_time(start), idx);
ReleaseMutex(mutex);
Sleep(et_time);//ест
WaitForSingleObject(mutex, INFINITE);
printf("%d:%d:E->T\n", get_time(start), idx);
phil_state[idx - 1] = 0;
phil_count--;
ReleaseMutex(mutex);
}
else
ReleaseMutex(mutex);
}
//printf("thread %d has finished \n", idx);
return 0;
}
//source\repos\phil\Debug\phil 50 10
int main(int argc, char* argv[])
{
if (argc !=3)
{
printf("ARGS ERROR \n");
return -1;
}
total = atoi(argv[1]);
et_time = atoi(argv[2]);
max_time = total + et_time;
memset(&threads, 0, sizeof(threads));
mutex = CreateMutex(NULL, FALSE, NULL);
event = CreateEvent(NULL, FALSE, TRUE, NULL);
for (int i = 0; i < phil_num; i++)
threads[i] = CreateThread(0, 0, philosopher, (void*)((char*)0 + i), 0, 0);
start = clock();
WaitForMultipleObjects(phil_num, threads, TRUE, INFINITE);
for (int i = 0; i < phil_num; i++)
CloseHandle(threads[i]);
CloseHandle(mutex);
CloseHandle(event);
return 0;
}
int get_time(time_t start)
{
return 1000 * ((double)clock() - (double)start) / (double)CLOCKS_PER_SEC;
}
bool is_possible(int phil_id)
{
if (phil_id == 1)
{
if (phil_state[1] == 0 && phil_state[4] == 0)
return 1;
}
else if (phil_id == 5)
{
if (phil_state[0] == 0 && phil_state[3] == 0)
return 1;
}
else if (phil_state[phil_id - 2] == 0 && phil_state[phil_id] == 0)
return 1;
return 0;
}