// Dining Philosophers: // Is a deadlock really possible? #include #include #include const int NUM_PHIL = 5; const int MAX_EATINGS = 50; const int THINK_TIME_DT = 40; // millisec const int THINK_TIME_MAX = 2 * THINK_TIME_DT; const int EAT_TIME_DT = 20; const int EAT_TIME_MAX = 2 * EAT_TIME_DT; const int TAKE_TIME_DT = 10; const int TAKE_TIME_MAX = 2 * TAKE_TIME_DT; // Thread body function DWORD WINAPI phil(void* n); static HANDLE hFork[NUM_PHIL]; static HANDLE hPrintMutex = NULL; int leftFork(int n); int rightFork(int n); void message(int n, const char *txt); static int curtime = 7959139; int main(int argc, char *argv[]) { HANDLE hThread[NUM_PHIL]; DWORD threadID[NUM_PHIL]; int num[NUM_PHIL]; if (argc > 1) { curtime = (int) GetTickCount(); fprintf(stderr,"curtime=%d\n", curtime); } hPrintMutex = CreateMutex( NULL, // default security attributes FALSE, // initially not owned NULL // unnamed mutex ); if (hPrintMutex == NULL) { printf( "Cannot create a printing mutex: error %d\n", GetLastError() ); exit(-1); } // Create the mutex for each fork for (int i = 0; i < NUM_PHIL; ++i) { num[i] = i; hFork[i] = CreateMutex( NULL, // default security attributes FALSE, // initially not owned NULL // unnamed mutex ); if (hFork[i] == NULL) { printf( "Cannot create a mutex %d: error %d\n", i, GetLastError() ); exit(-1); } } // Create the thread for each philosopher for (int i = 0; i < NUM_PHIL; ++i) { hThread[i] = CreateThread( NULL, // lpThreadAttributes 0, // dwStackSize - default &phil, // thread starting function (void *) &(num[i]), // argument of thread function 0, // dwCreationFlags &(threadID[i]) ); if (hThread[i] == NULL) { printf( "Cannot create thread %d: error %d\n", i, GetLastError() ); exit(-1); } } // Wait until threads terminate WaitForMultipleObjects(NUM_PHIL, hThread, TRUE, INFINITE); printf("OK!\n"); for (int i = 0; i < NUM_PHIL; ++i) { CloseHandle(hThread[i]); } for (int i = 0; i < NUM_PHIL; ++i) { CloseHandle(hFork[i]); } CloseHandle(hPrintMutex); return 0; } DWORD WINAPI phil(void* arg) { int n = *((int *) arg); srand(curtime + 997*n); // Set the random generator int numEats = 0; HANDLE hLeftFork = hFork[leftFork(n)]; HANDLE hRightFork = hFork[rightFork(n)]; while (numEats < MAX_EATINGS) { // Think a little... int t = rand() % (THINK_TIME_MAX / THINK_TIME_DT); Sleep((t + 1) * THINK_TIME_DT); // Take the left fork WaitForSingleObject(hLeftFork, INFINITE); message(n, "took left fork"); // Time between taking the left and the right forks t = rand() % (TAKE_TIME_MAX / TAKE_TIME_DT); Sleep((t + 1) * TAKE_TIME_DT); // Take the right fork WaitForSingleObject(hRightFork, INFINITE); message(n, "took right fork"); // Eating message(n, "eating"); t = rand() % (EAT_TIME_MAX / EAT_TIME_DT); Sleep((t + 1) * EAT_TIME_DT); // Release the left fork ReleaseMutex(hLeftFork); message(n, "released left fork"); // Release the right fork ReleaseMutex(hRightFork); message(n, "released right fork"); ++numEats; } // end wile return 0; } int leftFork(int n) { return n; } int rightFork(int n) { if (n < NUM_PHIL - 1) return n + 1; else return 0; } void message(int n, const char *txt) { WaitForSingleObject(hPrintMutex, INFINITE); printf("%d: %s\n", n+1, txt); ReleaseMutex(hPrintMutex); }