/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* threads.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: erey-bet +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/08 20:08:33 by erey-bet #+# #+# */ /* Updated: 2023/04/07 15:19:34 by erey-bet ### ########.fr */ /* */ /* ************************************************************************** */ #include "philo.h" void take_fork(t_philo *philo, int id_fork) { pthread_mutex_lock(&philo->same->mutex[id_fork]); philo->same->forks[id_fork] = 0; pthread_mutex_unlock(&philo->same->mutex[id_fork]); } void drop_fork(t_philo *philo, int id_fork, int next_id_fork) { pthread_mutex_lock(&philo->same->mutex[id_fork]); philo->same->forks[id_fork] = 1; pthread_mutex_unlock(&philo->same->mutex[id_fork]); if (next_id_fork >= 0) { pthread_mutex_lock(&philo->same->mutex[next_id_fork]); philo->same->forks[next_id_fork] = 1; pthread_mutex_unlock(&philo->same->mutex[next_id_fork]); } } int get_fork(t_philo *philo, int id_fork) { int fork; pthread_mutex_lock(&philo->same->mutex[id_fork]); fork = philo->same->forks[id_fork]; pthread_mutex_unlock(&philo->same->mutex[id_fork]); return (fork); } int finish(t_philo *philo, long long last_eat_time) { int dead; int all_eat; int nbr_philo; nbr_philo = philo->same->config->nbr_philo; if (philo->same->config->must_eat > -1) { pthread_mutex_lock(&philo->same->mutex[nbr_philo + 1]); all_eat = philo->same->all_eat; pthread_mutex_unlock(&philo->same->mutex[nbr_philo + 1]); } pthread_mutex_lock(&philo->same->mutex[nbr_philo]); dead = philo->same->death; pthread_mutex_unlock(&philo->same->mutex[nbr_philo]); return (get_utime() - last_eat_time >= philo->same->config->time_die || dead || (philo->same->config->must_eat != -1 && all_eat >= philo->same->config->must_eat * nbr_philo) ); } void init_philo(t_philo *philo, t_only *only, t_config *config, int *nbr_philo) { *nbr_philo = philo->same->config->nbr_philo; only->next_id = (only->id + 1) % *nbr_philo; only->last_eat_time = get_utime(); if (only->id % 2 == 1 || (*nbr_philo % 2 == 1 && only->id == *nbr_philo - 1)) { message(philo, "is thinking\n"); if (get_utime() - only->last_eat_time + config->time_eat >= config->time_die) usleep(config->time_die - (get_utime() - only->last_eat_time)); else usleep(config->time_eat / (only->id % 2 + 1)); } } int in_loop_eat_sleep(t_philo *philo, t_only *only, t_config *config, int nbr_philo) { only->last_eat_time = get_utime(); if (!verif_die_eating(philo, only, config)) return (0); usleep(config->time_eat); if (verif_finish(philo, only)) return (0); if (config->must_eat > -1 && only->eat < config->must_eat) { only->eat++; pthread_mutex_lock(&philo->same->mutex[nbr_philo + 1]); philo->same->all_eat += 1; pthread_mutex_unlock(&philo->same->mutex[nbr_philo + 1]); } message(philo, "is sleeping\n"); drop_fork(philo, only->id, only->next_id); if (get_utime() - only->last_eat_time + config->time_sleep >= config->time_die) { usleep(config->time_die - (get_utime() - only->last_eat_time)); return (0); } else usleep(config->time_sleep); return (1); } void loop_philosopher(t_philo *philo, t_only *only, t_config *config, int nbr_philo) { while (!finish(philo, only->last_eat_time)) { while (!finish(philo, only->last_eat_time) && get_fork(philo, only->id)) { take_fork(philo, only->id); message(philo, "has taken a fork\n"); while (only->id == only->next_id && !finish(philo, only->last_eat_time)) ; while (!finish(philo, only->last_eat_time) && get_fork(philo, only->next_id)) { if (verif_finish(philo, only)) break ; message(philo, "has taken a fork\n"); message(philo, "is eating\n"); if (!in_loop_eat_sleep(philo, only, config, nbr_philo)) break ; } drop_fork(philo, only->id, -1); } if (!finish(philo, only->last_eat_time)) message(philo, "is thinking\n"); } } void *philosopher(t_philo *philo) { t_only *only; t_config *config; int nbr_philo; only = philo->only; config = philo->same->config; init_philo(philo, only, config, &nbr_philo); loop_philosopher(philo, only, config, nbr_philo); pthread_mutex_lock(&philo->same->mutex[nbr_philo]); if (!philo->same->death && (config->must_eat == -1 || (config->must_eat > -1 && only->eat < config->must_eat))) { philo->same->death = 1; message_die(philo, "died\n"); } pthread_mutex_unlock(&philo->same->mutex[nbr_philo]); return (NULL); }