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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2020/02/14 22:45:23 by cacharle #+# #+# */
/* Updated: 2021/01/08 16:32:15 by charles ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo_two.h"
#define PHILO_SEM_NAME "semaphore_philo_two"
#define PHILO_SEM_STDOUT_NAME "semaphore_philo_two_stdout"
#define PHILO_SEM_FINISH_NAME "semaphore_philo_two_finish"
#define PHILO_SEM_START_NAME "semaphore_philo_two_start"
static int st_destroy(
t_philo *philos,
pthread_t *threads)
{
sem_unlink(PHILO_SEM_NAME);
sem_unlink(PHILO_SEM_STDOUT_NAME);
sem_unlink(PHILO_SEM_FINISH_NAME);
sem_unlink(PHILO_SEM_START_NAME);
free(philos);
free(threads);
return (1);
}
static bool st_sem_create(const char *name, unsigned int value, sem_t **sem)
{
sem_unlink(name);
return ((*sem = sem_open(name, O_CREAT | O_EXCL, 0700, value))
!= SEM_FAILED);
}
void *routine_flush(t_philo_conf *conf)
{
while (true)
{
sem_wait(conf->sem_stdout);
philo_put_flush();
sem_post(conf->sem_stdout);
usleep(250000);
}
}
static int st_setup(
t_philo_conf *conf,
t_philo **philos,
sem_t **forks,
pthread_t **threads)
{
long int i;
if (!st_sem_create(PHILO_SEM_NAME, conf->philo_num, forks) ||
!st_sem_create(PHILO_SEM_STDOUT_NAME, 1, &conf->sem_stdout) ||
!st_sem_create(PHILO_SEM_FINISH_NAME,
conf->meal_num == -1 ? 1 : conf->philo_num, &conf->sem_finish) ||
!st_sem_create(PHILO_SEM_START_NAME, conf->philo_num, &conf->sem_start))
return (1);
*threads = NULL;
if ((*philos = routine_create_philos(conf, *forks)) == NULL ||
(*threads = malloc(sizeof(pthread_t) * conf->philo_num)) == NULL)
return (st_destroy(*philos, *threads));
i = -1;
while (++i < conf->philo_num)
sem_wait(conf->sem_start);
conf->initial_time = h_time_now();
i = -1;
while (++i < conf->philo_num)
if (pthread_create(*threads + i, NULL,
(t_routine)routine_philo, *philos + i) != 0)
{
while (--i >= 0)
pthread_detach((*threads)[i]);
return (st_destroy(*philos, *threads));
}
return (0);
}
static void st_wait(t_philo_conf *conf)
{
long int i;
if (conf->meal_num == -1)
{
sem_wait(conf->sem_finish);
sem_wait(conf->sem_finish);
}
else
{
i = -1;
while (++i < conf->philo_num)
sem_wait(conf->sem_finish);
i = -1;
while (++i < conf->philo_num)
sem_wait(conf->sem_finish);
}
}
int main(int argc, char **argv)
{
long int i;
t_philo_conf conf;
t_philo *philos;
sem_t *forks;
pthread_t *threads;
if (!parse_args((t_philo_args *)&conf, argc, argv))
return (1);
if (conf.philo_num == 0 || conf.meal_num == 0)
return (0);
if (st_setup(&conf, &philos, &forks, &threads) != 0)
return (1);
pthread_t thread_flush;
pthread_create(&thread_flush, NULL, (t_routine)routine_flush, (void*)&conf);
pthread_detach(thread_flush);
i = -1;
while (++i < conf.philo_num)
sem_post(conf.sem_start);
st_wait(&conf);
philo_put_flush();
i = -1;
while (++i < conf.philo_num)
pthread_detach(threads[i]);
st_destroy(philos, threads);
return (0);
}
|