Синхронизация обедающих философов мьютексами и событием

Пытаюсь решить задачу обедающих философов. Согласно заданию, необходимо использовать и мьютекс, и событие. Основное внимание уделяется состоянию философов, а не вилок. Создавать вспомогательный поток нельзя. Программа является консольной и запускается с 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;
}

Ответы (0 шт):