/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* threads.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: erey-bet +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/08 20:08:33 by erey-bet #+# #+# */ /* Updated: 2023/04/01 11:57:59 by erey-bet ### ########.fr */ /* */ /* ************************************************************************** */ #include "philo.h" 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->time = get_utime(); only->last_eat_time = only->time; 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) { if (!verif_die_eating(philo, only, config)) return (0); usleep(config->time_eat); only->last_eat_time = get_utime(); 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"); pthread_mutex_unlock(&philo->same->mutex[only->next_id]); pthread_mutex_unlock(&philo->same->mutex[only->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)) { if (!finish(philo, only->last_eat_time) && !pthread_mutex_lock(&philo->same->mutex[only->id])) { message(philo, "has taken a fork\n"); while (only->id == only->next_id && !finish(philo, only->last_eat_time)) ; if (!finish(philo, only->last_eat_time) && !pthread_mutex_lock(&philo->same->mutex[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 ; } else pthread_mutex_unlock(&philo->same->mutex[only->id]); } 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 + 1]); 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]); pthread_mutex_unlock(&philo->same->mutex[nbr_philo + 1]); return (NULL); }