-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdining-philosophers-2.c
101 lines (86 loc) · 2.67 KB
/
dining-philosophers-2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// This example code is from: https://rosettacode.org/wiki/Dining_philosophers#C
// Please let me know if this does not constitute fair use.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// When building, you must link with the external pthread library: for example, 'gcc dining-philosophers-2.c -lpthread'
// This solution makes use of functions like 'trylock' to avoid deadlock.
typedef struct philData {
pthread_mutex_t *fork_lft, *fork_rgt;
const char *name;
pthread_t thread;
int fail;
} Philosopher;
int running = 1;
void *PhilPhunction(void *p) {
Philosopher *phil = (Philosopher*)p;
int failed;
int tries_left;
pthread_mutex_t *fork_lft, *fork_rgt, *fork_tmp;
while (running) {
printf("%s is sleeping --er thinking\n", phil->name);
sleep( 1+ rand()%8);
fork_lft = phil->fork_lft;
fork_rgt = phil->fork_rgt;
printf("%s is hungry\n", phil->name);
tries_left = 2; /* try twice before being forceful */
do {
failed = pthread_mutex_lock( fork_lft);
failed = (tries_left>0)? pthread_mutex_trylock( fork_rgt )
: pthread_mutex_lock(fork_rgt);
if (failed) {
pthread_mutex_unlock( fork_lft);
fork_tmp = fork_lft;
fork_lft = fork_rgt;
fork_rgt = fork_tmp;
tries_left -= 1;
}
} while(failed && running);
if (!failed) {
printf("%s is eating\n", phil->name);
sleep( 1+ rand() % 8);
pthread_mutex_unlock( fork_rgt);
pthread_mutex_unlock( fork_lft);
}
}
return NULL;
}
void Ponder()
{
const char *nameList[] = { "Kant", "Guatma", "Russel", "Aristotle", "Bart" };
pthread_mutex_t forks[5];
Philosopher philosophers[5];
Philosopher *phil;
int i;
int failed;
for (i=0;i<5; i++) {
failed = pthread_mutex_init(&forks[i], NULL);
if (failed) {
printf("Failed to initialize mutexes.");
exit(1);
}
}
for (i=0;i<5; i++) {
phil = &philosophers[i];
phil->name = nameList[i];
phil->fork_lft = &forks[i];
phil->fork_rgt = &forks[(i+1)%5];
phil->fail = pthread_create( &phil->thread, NULL, PhilPhunction, phil);
}
sleep(40);
running = 0;
printf("cleanup time\n");
for(i=0; i<5; i++) {
phil = &philosophers[i];
if ( !phil->fail && pthread_join( phil->thread, NULL) ) {
printf("error joining thread for %s", phil->name);
exit(1);
}
}
}
int main()
{
Ponder();
return 0;
}