#include <windows.h>
#include <process.h>
#include <time.h>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#define NUM 5
#define UNUSED 0xffff
BOOL bFast = FALSE;
#define P_DELAY bFast ? rand()/10 : ((rand()%5)+1)*1000
enum DinnerStatus
{
RESTING,
WAITING,
EATING
};
HANDLE hChopstickMutex[NUM];
DinnerStatus sDinner[NUM];
UINT wChopstickStatus[NUM];
HANDLE hThread[NUM];
UINT wThreadId[NUM];
CRITICAL_SECTION cs;
UINT WINAPI run(LPVOID pArg)
{
DWORD ret = 0;
HANDLE hCurChopstick[2] = { NULL };
UINT curPhilo = (UINT)pArg;
UINT wLeftChopstick = curPhilo;
UINT wRightChopstick = curPhilo+1;
if (wRightChopstick >= NUM)
wRightChopstick = 0;
srand((unsigned int)time(NULL)*(curPhilo+1));
hCurChopstick[0] = hChopstickMutex[wLeftChopstick];
hCurChopstick[1] = hChopstickMutex[wRightChopstick];
sDinner[curPhilo] = RESTING;
EnterCriticalSection(&cs);
cout << "Dinner: " << curPhilo << " is RESTING" << endl;
LeaveCriticalSection(&cs);
Sleep(P_DELAY);
for (;;)
{
if (bFast)
{
sDinner[curPhilo] = WAITING;
EnterCriticalSection(&cs);
cout << "*******Dinner: " << curPhilo << " is WAITING" << endl;
LeaveCriticalSection(&cs);
ret = WaitForMultipleObjects(2, hCurChopstick, TRUE, INFINITE);
if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0+2)
{
wChopstickStatus[wLeftChopstick] = curPhilo;
wChopstickStatus[wRightChopstick] = curPhilo;
EnterCriticalSection(&cs);
cout << "*******Chopstick<" << wLeftChopstick << "," << wRightChopstick << "> owned by " << curPhilo << endl;
LeaveCriticalSection(&cs);
}
}
else
{
sDinner[curPhilo] = WAITING;
EnterCriticalSection(&cs);
cout << "Dinner: " << curPhilo << " is WAITING" << endl;
LeaveCriticalSection(&cs);
ret = WaitForSingleObject(hChopstickMutex[wLeftChopstick], INFINITE);
if (WAIT_OBJECT_0 == ret)
{
wChopstickStatus[wLeftChopstick] = curPhilo;
EnterCriticalSection(&cs);
cout << "Chopstick<" << wLeftChopstick << "> is owned by " << curPhilo << endl;
LeaveCriticalSection(&cs);
}
Sleep(P_DELAY/4);
ret = WaitForSingleObject(hChopstickMutex[wRightChopstick], INFINITE);
if (WAIT_OBJECT_0 == ret)
{
wChopstickStatus[wRightChopstick] = curPhilo;
EnterCriticalSection(&cs);
cout << "Chopstick<" << wRightChopstick << "> is owned by " << curPhilo << endl;
LeaveCriticalSection(&cs);
}
}
sDinner[curPhilo] = EATING;
EnterCriticalSection(&cs);
cout << "Dinner: " << curPhilo << " is EATING" << endl;
LeaveCriticalSection(&cs);
Sleep(P_DELAY);
// put down the chop stick
ReleaseMutex(hChopstickMutex[wLeftChopstick]);
ReleaseMutex(hChopstickMutex[wRightChopstick]);
sDinner[curPhilo] = RESTING;
wChopstickStatus[wLeftChopstick] = UNUSED;
wChopstickStatus[wRightChopstick] = UNUSED;
EnterCriticalSection(&cs);
cout << "Dinner: " << curPhilo << " is Full, is RESTING and put down chopsticks<" << wLeftChopstick << "," << wRightChopstick << ">" << endl;
LeaveCriticalSection(&cs);
Sleep(P_DELAY);
}
return 0;
}
void Init()
{
for (int i = 0; i < NUM; ++i)
{
wChopstickStatus[i] = UNUSED;
sDinner[i] = RESTING;
hChopstickMutex[i] = CreateMutex(NULL, FALSE, NULL);
if (NULL == hChopstickMutex[i])
cout << "Fail to create event " << i << endl;
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, run, (LPVOID)i, CREATE_SUSPENDED, &wThreadId[i]);
if (NULL == hThread[i])
cout << "Fail to create thread " << i << endl;
}
InitializeCriticalSection(&cs);
}
void Start()
{
for (int i = 0; i < NUM; ++i)
{
Sleep(i*200);
if (-1 == ResumeThread(hThread[i]))
cout << "Fail to start thread: " << i << endl;
}
}
void Cleanup()
{
for (int i = 0; i < NUM; ++i)
{
CloseHandle(hThread[i]);
hThread[i] = NULL;
CloseHandle(hChopstickMutex[i]);
hChopstickMutex[i] = NULL;
}
DeleteCriticalSection(&cs);
}
int main()
{
cout << "Please choose fast food(1:fast, 0:slow)" << endl;
cin >> bFast;
Init();
Start();
Sleep(15000);
Cleanup();
return 0;
}