Created
October 23, 2019 14:09
-
-
Save poi519/8dc5670e295dc935b58fa080634969ed to your computer and use it in GitHub Desktop.
Dining philosophers in C using WinApi. Running: philosophers.exe 10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
int fix = FALSE; | |
DWORD WINAPI dine(LPVOID param); | |
typedef struct { | |
int id; | |
HANDLE mutex; | |
} Fork; | |
typedef struct { | |
int id; | |
Fork *left; | |
Fork *right; | |
} Philosopher; | |
int main(int argc, char **argv) { | |
int num = 3; | |
if (argc > 1) { | |
num = (int) strtol(argv[1], (char **) NULL, 10); | |
printf("%u\n", num); | |
} | |
if (num < 1) { | |
return 0; | |
} | |
if (argc > 2) { | |
fix = TRUE; | |
} | |
Fork *forks = malloc(num * sizeof(Fork)); | |
Philosopher *ph = malloc(num * sizeof(Philosopher)); | |
DWORD *threadIds = malloc(num * sizeof(DWORD)); | |
HANDLE *threads = malloc(num * sizeof(HANDLE)); | |
for (int i = 0; i < num; i++) { | |
forks[i].id = i; | |
forks[i].mutex = CreateMutex( | |
NULL, // default security attributes | |
FALSE, // initially not owned | |
NULL); // unnamed mutex | |
if (forks[i].mutex == NULL) { | |
printf("CreateMutex error"); | |
return 1; | |
} | |
} | |
for (int i = 0; i < num; i++) { | |
ph[i].id = i; | |
} | |
for (int i = 0; i < num - 1; i++) { | |
ph[i].left = &forks[i]; | |
ph[i].right = &forks[i + 1]; | |
} | |
ph[num - 1].left = &forks[num - 1]; | |
ph[num - 1].right = &forks[0]; | |
for (int i = 0; i < num; i++) { | |
threads[i] = CreateThread( | |
NULL, | |
0, | |
dine, | |
&ph[i], | |
0, | |
&threadIds[i]); | |
if (threads[i] == NULL) { | |
printf("Error creating thread"); | |
ExitProcess(3); | |
} | |
} | |
WaitForMultipleObjects(num, threads, TRUE, INFINITE); | |
free(forks); | |
free(ph); | |
free(threads); | |
free(threadIds); | |
return 0; | |
} | |
void acquireFork(Philosopher *phi, Fork *f) { | |
DWORD waitResult; | |
printf("Philosopher %u, acquiring fork %u \n", phi->id, f->id); | |
waitResult = WaitForSingleObject(f->mutex, INFINITE); | |
switch (waitResult) { | |
case WAIT_OBJECT_0: { | |
printf("Philosopher %u, acquired fork %u \n", phi->id, f->id); | |
break; | |
} | |
case WAIT_ABANDONED: { | |
printf("Philsopher %u, abandoned wait for fork %u \n", phi->id, f->id); | |
} | |
} | |
} | |
void releaseFork(Philosopher *phi, Fork *f) { | |
printf("Philosopher %u, releasing fork %u \n", phi->id, f->id); | |
if (!ReleaseMutex(f->mutex)) { | |
printf("Philosopher %u, cannot release fork %u \n", phi->id, f->id); | |
} | |
} | |
DWORD WINAPI dine(LPVOID param) { | |
Philosopher *phi = (Philosopher *) param; | |
Fork *first = phi->left; | |
Fork *last = phi->right; | |
if (fix) { | |
if (phi->right->id < phi->left->id) { | |
first = phi->right; | |
last = phi->left; | |
} | |
} | |
acquireFork(phi, first); | |
Sleep(100); | |
acquireFork(phi, last); | |
printf("Philosopher %u dining\n", phi->id); | |
Sleep(1000); | |
releaseFork(phi, first); | |
Sleep(100); | |
releaseFork(phi, last); | |
return TRUE; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment