구현순서
- argv 확인
- 파싱 및 초기화
- 스레드 생성
먹기
잠자기
생각하기
- 모니터링하기
- 리소스 회수하고 종료하기
Main
#include "philosophers.h"
int main(int argc, char *argv[])
{
t_param param;
if (argc != 5 && argc != 6)
return (ft_error("[Error]check num of arg"));
if (ft_philo_init(argc, argv, ¶m))
return (1);
if (ft_start_philo(¶m, (¶m)->philo))
return (1);
return (0);
}
argv확인
int check_is_num(char *str)
{
int i;
i = 0;
while (str[i] != '\0')
{
if (str[i] < '0' || str[i] > '9')
return (1);
i++;
}
return (0);
}
int check_argv(int argc, char *argv[])
{
int i;
i = 1;
while (i != argc)
{
if (check_is_num(argv[i]))
return (1);
i++;
}
if (ft_atoi(argv[1]) < 1)
return (1);
if (ft_atoi(argv[2]) < 0)
return (1);
if (ft_atoi(argv[3]) < 0)
return (1);
if (ft_atoi(argv[4]) < 0)
return (1);
if (argc == 6)
if (ft_atoi(argv[5]) < 0)
return (1);
return (0);
}
파싱 및 초기화
int ft_philo_init(int argc, char *argv[], t_param *par)
{
int i;
i = 0;
if (check_argv(argc, argv))
return (ft_error("[Error]check argv data"));
par->philo_num = ft_atoi(argv[1]);
par->time_to_die = ft_atoi(argv[2]);
par->time_to_eat = ft_atoi(argv[3]);
par->time_to_sleep = ft_atoi(argv[4]);
if (argc == 6)
par->must_eat_num = ft_atoi(argv[5]);
else
par->must_eat_num = -1;
if (par->must_eat_num == 0)
return (ft_error("0ms all philo eat 0 time));
par->fork_st = malloc(sizeof(int) * par->philo_num);
if (par->fork_st == NULL)
return (ft_error("[Error]malloc fork fail"));
while (i < par->philo_num)
par->fork_st[i++] = 0;
par->is_all_safe = 1;
if (ft_make_philo(par))
return (ft_error("[Error]malloc philo fail"));
if (ft_make_forks(par))
return (1);
return (0);
}
int ft_make_philo(t_param *par)
{
int i;
i = 0;
par->philo = malloc(sizeof(t_param) * (par->philo_num));
if (par->philo == NULL)
return (1);
while (i < par->philo_num)
{
par->philo[i].eat_count = 0;
par->philo[i].last_eat_time = 0;
par->philo[i].leftfork = i;
par->philo[i].rightfork = i + 1;
par->philo[i].param = par;
par->philo[i].philo_id = i + 1;
if (i != 0 && i + 1 == par->philo_num)
par->philo[i].rightfork = 0;
i++;
}
return (0);
}
int ft_make_forks(t_param *param)
{
int i;
i = 0;
if (pthread_mutex_init(&(param->print), NULL))
return (ft_error("[Error]print mutex init fail"));
if (pthread_mutex_init(&(param->search_fork), NULL))
return (ft_error("[Error]search_fork mutex init fail"));
if (pthread_mutex_init(&(param->eat), NULL))
return (ft_error("[Error]eat mutex init fail"));
param->forks = malloc(sizeof(pthread_mutex_t) * (param->philo_num));
if (param->forks == NULL)
return (ft_error("[Error]malloc forks fail"));
while (i < param->philo_num)
{
if (pthread_mutex_init(¶m->forks[i], NULL))
return (ft_error("[Error]forks mutex init fail"));
i++;
}
return (0);
}
스레드 생성
int ft_start_philo(t_param *par, t_philo *philo)
{
int i;
void *philo_v;
i = 0;
par->start_time = ft_get_time();
while (i < par->philo_num)
{
philo_v = (void *)&(philo[i]);
if (pthread_create(&(philo[i].tid), NULL, do_philo, philo_v) == -1)
return (ft_error("[Error]thread create fail"));
i++;
}
ft_wait(par, par->time_to_eat);
ft_check_die(par);
return (0);
}
스레드 내부
void *do_philo(void *philo)
{
t_philo *phil;
t_param *param;
phil = (t_philo *)philo;
param = phil->param;
if (phil->philo_id % 2 != 1)
ft_wait(param, 1);
while (param->is_all_safe)
{
while (get_fork1(phil, param))
usleep(100);
do_sleep(phil, param);
do_think(phil, param);
usleep(100);
}
return (0);
}
먹기
int get_fork1(t_philo *p, t_param *param)
{
if (param->is_all_safe == 0)
return (0);
pthread_mutex_lock(¶m->search_fork);
if (param->fork_st[p->leftfork] == 0 && param->fork_st[p->rightfork] == 0)
{
pthread_mutex_lock(¶m->forks[p->leftfork]);
ft_print(param, p, "has taken a fork");
param->fork_st[p->leftfork] = 1;
pthread_mutex_lock(¶m->forks[p->rightfork]);
ft_print(param, p, "has taken a fork");
param->fork_st[p->rightfork] = 1;
do_eat(p, param);
pthread_mutex_unlock(¶m->search_fork);
ft_wait(param, param->time_to_eat);
param->fork_st[p->leftfork] = 0;
param->fork_st[p->rightfork] = 0;
pthread_mutex_unlock(¶m->forks[p->leftfork]);
pthread_mutex_unlock(¶m->forks[p->rightfork]);
p->eat_count++;
return (0);
}
pthread_mutex_unlock(¶m->search_fork);
return (1);
}
void do_eat(t_philo *philo, t_param *param)
{
long long time;
if (param->is_all_safe == 0)
time = 0;
else
{
pthread_mutex_lock(&(param->eat));
time = ft_get_time() - param->start_time;
philo->last_eat_time = time;
ft_print(param, philo, "is eating");
pthread_mutex_unlock(&(param->eat));
}
}
잠자기
void do_sleep(t_philo *philo, t_param *param)
{
if (param->is_all_safe == 0)
param->is_all_safe = 0;
else
{
ft_print(param, philo, "is sleeping");
ft_wait(param, param->time_to_sleep);
}
}
생각하기
void do_think(t_philo *philo, t_param *param)
{
if (param->is_all_safe == 0)
param->is_all_safe = 0;
else
{
ft_print(param, philo, "is thinking");
}
}
모니터링하기
void ft_check_die(t_param *par)
{
while (par->is_all_safe)
{
pthread_mutex_lock(&(par->eat));
if (check_eat_time(par))
break ;
if (par->must_eat_num != -1)
if (check_eat_num(par))
break ;
pthread_mutex_unlock(&(par->eat));
usleep(100);
}
pthread_mutex_unlock(&(par->eat));
finish_thread(par);
}
식사시간 확인
int check_eat_time(t_param *p)
{
long long time;
int i;
i = 0;
while (i < p->philo_num)
{
time = ft_get_time() - p->start_time;
if ((time - p->philo[i].last_eat_time) > p->time_to_die)
{
pthread_mutex_lock(&p->print);
p->is_all_safe = 0;
printf("%lldms %d is died\n", time, p->philo[i].philo_id);
pthread_mutex_unlock(&p->print);
return (1);
}
i++;
}
return (0);
}
식사횟수 확인
int check_eat_num(t_param *p)
{
long long time;
int i;
int check;
i = 0;
check = 0;
while (i < p->philo_num)
{
if (p->philo[i].eat_count >= p->must_eat_num && p->must_eat_num != -1)
check++;
i++;
}
if (check == p->philo_num)
{
pthread_mutex_lock(&p->print);
p->is_all_safe = 0;
time = ft_get_time() - p->start_time;
printf("%lldms all philo eat %d time\n", time, p->must_eat_num);
pthread_mutex_unlock(&p->print);
return (1);
}
return (0);
}
리소스 회수하고 종료하기
void finish_thread(t_param *param)
{
int i;
i = 0;
while (i < param->philo_num)
{
pthread_join(param->philo[i].tid, NULL);
i++;
}
i = 0;
while (i < param->philo_num)
{
pthread_mutex_destroy(&(param->forks[i]));
i++;
}
free(param->forks);
free(param->philo);
free(param->fork_st);
pthread_mutex_destroy(&(param->print));
pthread_mutex_destroy(&(param->eat));
pthread_mutex_destroy(&(param->search_fork));
}
안녕하세요, 질문이 있는데 혹시 해도 될까요?