commit 34c92494e857e96f0043df5ebed5b82e2817f3a7 Author: root Date: Sat Nov 15 22:31:33 2025 +0000 intra to gitea diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fb222a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,82 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: lfirmin lfirmim@student.42.fr> +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2024/08/12 07:07:31 by lfirmin #+# #+# # +# Updated: 2024/08/12 09:15:05 by lfirmin ### ########.fr # +# # +# **************************************************************************** # + +NAME = philo +SRC_FILES = main.c parsing.c utils.c utils_2.c routine.c threads.c routine_utils.c init.c death.c routine_utils_2.c +INCLUDES_FILES = include/philo.h +SRC_DIR = srcs/ +SRC = $(addprefix $(SRC_DIR), $(SRC_FILES)) +OBJ_DIR = obj/ +OBJ = $(addprefix $(OBJ_DIR), $(SRC_FILES:.c=.o)) +CC = cc +CFLAGS = -Wall -Werror -Wextra -g3 -pthread +INCLUDE = -I include +RM = rm -rf +MKDIR = mkdir -p + +GREEN = \033[0;32m +YELLOW = \033[0;33m +CYAN = \033[0;36m +RESET = \033[0m +BOLD = \033[1m +WHITE = \033[0;97m + +LOADING_CHARS = ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏ + +define PHILO_ART + +|||| _____ _ _ _ |||| +|||| | __ \| | (_) | |||| +\__/ | |__) | |__ _| | ___ \__/ + || | ___/| '_ \| | |/ _ \ || + || | | | | | | | | (_) | || + || |_| |_| |_|_|_|\___/ || + "" "" +endef +export PHILO_ART + +all: print_art $(NAME) + +print_art: + @printf "$(YELLOW)%s$(RESET)\n" "$$PHILO_ART" + +$(NAME): $(OBJ) $(INCLUDES_FILES) + @printf "$(BOLD)$(WHITE)Welcome to the $(GREEN)Philosophers$(WHITE) compilation process.\nPlease hold on as we prepare your program.\n\n$(RESET)" + @printf "$(YELLOW)Compiling Philosophers, Please wait...$(RESET)" + @for char in $(LOADING_CHARS); do \ + printf "\r$(YELLOW)Compiling Philosophers, Please wait... $$char$(RESET)"; \ + sleep 0.1; \ + done + @$(CC) $(CFLAGS) $(OBJ) $(INCLUDE) -o $(NAME) + @printf "\r$(GREEN)Nice ! $(WHITE)Philosophers compiled successfully ! $(RESET)\n\n" + @printf "$(BOLD)$(WHITE)Compilation complete !\n$(GREEN)Philosophers$(WHITE) is ready to use !\n" + +$(OBJ_DIR)%.o: $(SRC_DIR)%.c + @$(MKDIR) $(OBJ_DIR) + @$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + @$(RM) $(OBJ_DIR) + @printf "$(WHITE)Clean process completed for $(GREEN)Philosophers.$(RESET)\n" + +fclean: clean + @$(RM) $(NAME) + @$(RM) $(PRINTF) + @$(RM) $(LIBFT) + @printf "$(WHITE)Full clean process completed for $(GREEN)Philosophers.$(RESET)\n" + +re: fclean all + +.PHONY: all clean fclean re print_art norminette + +norminette: + norminette srcs/* include/* | grep "Error" \ No newline at end of file diff --git a/include/philo.h b/include/philo.h new file mode 100644 index 0000000..e9a41c3 --- /dev/null +++ b/include/philo.h @@ -0,0 +1,92 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/21 15:38:19 by lfirmin #+# #+# */ +/* Updated: 2024/11/21 15:38:19 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#ifndef PHILO_H +# define PHILO_H + +# include +# include +# include +# include +# include +# include + +# define USAGE_MESS "Usage ► ./philo \ + [number_of_times_each_philosopher_must_eat]" + +typedef struct s_philo +{ + long long id; + int l_fork; + int r_fork; + long long last_meal; + int m_eaten; + pthread_t thread; + pthread_mutex_t meal_lock; + struct s_data *data; +} t_philo; + +typedef struct s_data +{ + long long nb_philo; + long long t_die; + long long t_eat; + long long t_sleep; + long long must_eat; + long long start_time; + pthread_mutex_t *forks; + pthread_mutex_t print; + pthread_mutex_t dead_mutex; + int dead_flag; + t_philo *philos; + int threads_active; + pthread_mutex_t threads_count_mutex; + pthread_cond_t threads_done_cond; +} t_data; + +//utils// +long long ft_atoll(const char *str); +t_data *init_data(void); +void free_data(t_data *data); +long long get_time(void); +void *death_check(void *arg); +int create_threads(t_data *data); +int check_if_dead(t_philo *philo); +int check_if_dead_data(t_data *data); +int print_message(t_philo *philo, char *message); + +//init// +int init_forks(t_data *data); +int init_philos(t_data *data); +int init_philo_forks(t_data *data); + +//parsing// +void ft_put_and_check_2(t_data *data, char **av, int *c); +int ft_put_and_check(t_data *data, char **av); +int validate_number(char **av, int i); +int ft_check_av(char **av); +int parsing(int ac, char **av, t_data *data); + +//routine// +int thinking(t_philo *philo); +int sleeping(t_philo *philo); +int eating(t_philo *philo); +void philo_routine_init(t_philo *philo); +void *philo_routine(void *arg); + +//routine_utils// +int eating_1_philo(t_philo *philo); +int take_fork_and_eat(t_philo *philo); +int take_fork_and_eat_alt(t_philo *philo); +int safe_sleep(t_philo *philo, long time); +int take_fork(t_philo *philo); +int ft_should_continue(t_philo *philo); +#endif \ No newline at end of file diff --git a/srcs/death.c b/srcs/death.c new file mode 100644 index 0000000..166c31d --- /dev/null +++ b/srcs/death.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* death.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 14:20:46 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 04:52:57 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +void set_dead_and_print(t_data *data, int philo_idx, long long current_time) +{ + pthread_mutex_lock(&data->dead_mutex); + data->dead_flag = 1; + pthread_mutex_unlock(&data->dead_mutex); + pthread_mutex_unlock(&data->philos[philo_idx].meal_lock); + pthread_mutex_lock(&data->print); + printf("%lld %lld died\n", current_time - data->start_time, + data->philos[philo_idx].id); + pthread_mutex_unlock(&data->print); +} + +static void set_all_ate_and_print(t_data *data) +{ + pthread_mutex_lock(&data->dead_mutex); + data->dead_flag = 1; + pthread_mutex_unlock(&data->dead_mutex); + pthread_mutex_lock(&data->print); + printf("Each philosopher has eaten %lld times\n", data->must_eat); + pthread_mutex_unlock(&data->print); +} + +static int check_philo_death(t_data *data, int idx, int *all_ate_enough) +{ + long long current_time; + long long time_since_last_meal; + + if (check_if_dead_data(data)) + return (1); + pthread_mutex_lock(&data->philos[idx].meal_lock); + current_time = get_time(); + time_since_last_meal = current_time - data->philos[idx].last_meal; + if (time_since_last_meal > data->t_die) + { + set_dead_and_print(data, idx, current_time); + return (1); + } + if (data->must_eat != -1 && data->philos[idx].m_eaten < data->must_eat) + *all_ate_enough = 0; + pthread_mutex_unlock(&data->philos[idx].meal_lock); + return (0); +} + +static int check_all_philos(t_data *data) +{ + int i; + int all_ate_enough; + + i = 0; + all_ate_enough = 1; + while (i < data->nb_philo) + { + if (check_philo_death(data, i, &all_ate_enough)) + return (1); + i++; + } + if (data->must_eat != -1 && all_ate_enough && !check_if_dead_data(data)) + { + set_all_ate_and_print(data); + return (1); + } + return (0); +} + +void *death_check(void *arg) +{ + t_data *data; + + data = (t_data *)arg; + while (1) + { + if (check_if_dead_data(data)) + return (NULL); + usleep(500); + if (check_all_philos(data)) + return (NULL); + } +} diff --git a/srcs/init.c b/srcs/init.c new file mode 100644 index 0000000..2337e47 --- /dev/null +++ b/srcs/init.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* init.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 14:20:46 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 04:12:57 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +int init_forks(t_data *data) +{ + int i; + + i = 0; + while (i < data->nb_philo) + { + if (pthread_mutex_init(&data->forks[i], NULL)) + return (1); + i++; + } + return (0); +} + +int init_philos(t_data *data) +{ + int i; + + i = 0; + while (i < data->nb_philo) + { + data->philos[i].id = i + 1; + data->philos[i].l_fork = i; + data->philos[i].r_fork = (i + 1) % data->nb_philo; + data->philos[i].last_meal = data->start_time; + data->philos[i].m_eaten = 0; + data->philos[i].data = data; + if (pthread_mutex_init(&data->philos[i].meal_lock, NULL)) + return (1); + i++; + } + return (0); +} + +int init_all(t_data *data) +{ + int i; + + i = -1; + if (init_philo_forks(data)) + return (printf("Error : Failed to allocate memory\n"), 1); + if (init_forks(data)) + { + free(data->philos); + free(data->forks); + return (printf("Error : Failed to initialize forks mutex\n"), 1); + } + if (init_philos(data)) + { + while (++i < data->nb_philo) + pthread_mutex_destroy(&data->forks[i]); + free(data->philos); + free(data->forks); + return (printf("Error : Failed to initialize philosophers\n"), 1); + } + return (0); +} + +int init_philo_forks(t_data *data) +{ + data->philos = malloc(sizeof(t_philo) * data->nb_philo); + if (!data->philos) + return (1); + data->forks = malloc(sizeof(pthread_mutex_t) * data->nb_philo); + if (!data->forks) + return (free(data->philos), 1); + return (0); +} diff --git a/srcs/main.c b/srcs/main.c new file mode 100644 index 0000000..759beb1 --- /dev/null +++ b/srcs/main.c @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/21 15:42:31 by lfirmin #+# #+# */ +/* Updated: 2025/04/17 13:48:43 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../include/philo.h" + +int setup_simulation(int ac, char **av, t_data **data, pthread_t *death_thread) +{ + *data = init_data(); + if (!*data) + return (1); + if (parsing(ac, av, *data)) + return (free_data(*data), 1); + if ((*data)->t_die <= 0 || (*data)->t_eat <= 0 || (*data)->t_sleep <= 0) + { + printf("Error: Time values must be positive integers\n"); + return (free_data(*data), 1); + } + if (init_philo_forks(*data)) + return (free_data(*data), 1); + if (init_forks(*data)) + return (free_data(*data), 1); + (*data)->start_time = get_time(); + if (init_philos(*data)) + return (free_data(*data), 1); + if (pthread_create(death_thread, NULL, &death_check, *data)) + { + printf("Error: Failed to create death check thread\n"); + return (free_data(*data), 1); + } + return (0); +} + +int main(int ac, char **av) +{ + t_data *data; + pthread_t death_thread; + + if (setup_simulation(ac, av, &data, &death_thread)) + return (1); + if (create_threads(data)) + { + pthread_mutex_lock(&data->dead_mutex); + data->dead_flag = 1; + pthread_mutex_unlock(&data->dead_mutex); + pthread_join(death_thread, NULL); + printf("Error: Failed to create philosopher threads\n"); + return (free_data(data), 1); + } + if (pthread_join(death_thread, NULL)) + { + printf("Error: Failed to join death check thread\n"); + return (free_data(data), 1); + } + return (free_data(data), 0); +} diff --git a/srcs/parsing.c b/srcs/parsing.c new file mode 100644 index 0000000..040ca55 --- /dev/null +++ b/srcs/parsing.c @@ -0,0 +1,97 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parsing.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/21 16:16:19 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 04:00:28 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +int ft_put_and_check(t_data *data, char **av) +{ + int c; + + c = 0; + data->nb_philo = ft_atoll(av[1]); + if (data->nb_philo <= 0) + (printf("Error : Invalid number of philo, expected 1 "\ + "or more, You gave \"%s\"\n", av[1]), c++); + data->t_die = ft_atoll(av[2]); + if (data->t_die <= 0) + (printf("Error : Invalid time for die, expected 1ms "\ + "or more, You gave \"%s\"\n", av[2]), c++); + data->t_eat = ft_atoll(av[3]); + if (data->t_eat < 0 || !av[3][0]) + (printf("Error : Invalid time for eat, expected 0ms "\ + "or more, You gave \"%s\"\n", av[3]), c++); + data->t_sleep = ft_atoll(av[4]); + if (data->t_sleep < 0 || !av[4][0]) + (printf("Error : Invalid time for sleep, expected 0ms "\ + "or more, You gave \"%s\"\n", av[4]), c++); + if (av[5] != NULL) + ft_put_and_check_2(data, av, &c); + return (c); +} + +void ft_put_and_check_2(t_data *data, char **av, int *c) +{ + data->must_eat = ft_atoll(av[5]); + if (data->must_eat < 1) + (printf("Error : Invalid number of philo must eat, expected 1 or more"\ + ", You gave \"%s\"\n", av[5]), (*c)++); +} + +int ft_check_av(char **av) +{ + int i; + int c; + + c = 0; + i = 1; + while (av[i]) + { + if (validate_number(av, i) == 1) + (printf("Error : argument %d isn't a number\n", i + 1), c++); + i++; + } + return (c); +} + +int validate_number(char **av, int i) +{ + int j; + + j = 0; + while (av[i][j]) + { + if ((av[i][j] < '0' || av[i][j] > '9') && \ + (av[i][j] != '-' && av[i][j] != '+')) + return (1); + if (av[i][j] == '-' || av[i][j] == '+') + { + if (av[i][j + 1] < '0' || av[i][j + 1] > '9' || j != 0) + return (1); + } + j++; + } + return (0); +} + +int parsing(int ac, char **av, t_data *data) +{ + int ret; + + if (ac < 5 || ac > 6) + return (printf("%s\n", USAGE_MESS), 1); + ret = ft_check_av(av); + if (ret != 0) + return (1); + ret = ft_put_and_check(data, av); + if (ret != 0) + return (1); + return (0); +} diff --git a/srcs/routine.c b/srcs/routine.c new file mode 100644 index 0000000..136429e --- /dev/null +++ b/srcs/routine.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* routine.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 14:47:26 by lfirmin #+# #+# */ +/* Updated: 2025/04/17 14:27:04 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +int eating(t_philo *philo) +{ + if (!philo) + return (1); + if (check_if_dead(philo)) + return (1); + if (take_fork_and_eat(philo)) + return (1); + return (0); +} + +int sleeping(t_philo *philo) +{ + if (check_if_dead(philo)) + return (1); + print_message(philo, "is sleeping"); + if (safe_sleep(philo, philo->data->t_sleep * 1000)) + return (1); + return (0); +} + +int thinking(t_philo *philo) +{ + if (print_message(philo, "is thinking")) + return (1); + if (philo->data->nb_philo % 2 == 0) + { + if (philo->data->t_eat > philo->data->t_sleep) + usleep((philo->data->t_eat - philo->data->t_sleep) * 1000); + } + else + { + if (2 * philo->data->t_eat > philo->data->t_sleep) + usleep((2 * philo->data->t_eat - philo->data->t_sleep) * 1000); + } + return (0); +} + +void philo_routine_init(t_philo *philo) +{ + if (philo->id % 2 == 0) + { + if (philo->data->nb_philo > 100) + usleep(500); + else + usleep(1000); + } + pthread_mutex_lock(&philo->meal_lock); + philo->last_meal = get_time(); + pthread_mutex_unlock(&philo->meal_lock); +} + +void *philo_routine(void *arg) +{ + t_philo *philo; + int should_continue; + + philo = (t_philo *)arg; + if (philo->data->nb_philo == 1) + return (eating_1_philo(philo), NULL); + if (philo->id % 2 == 0) + usleep(philo->data->t_eat * 500); + while (1) + { + pthread_mutex_lock(&philo->data->dead_mutex); + should_continue = ft_should_continue(philo); + pthread_mutex_unlock(&philo->data->dead_mutex); + if (!should_continue) + break ; + if (eating(philo) == 1) + break ; + if (sleeping(philo) == 1) + break ; + if (thinking(philo) == 1) + break ; + } + return (NULL); +} diff --git a/srcs/routine_utils.c b/srcs/routine_utils.c new file mode 100644 index 0000000..60cde7c --- /dev/null +++ b/srcs/routine_utils.c @@ -0,0 +1,90 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* routine_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 14:47:26 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 03:59:51 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +int eating_1_philo(t_philo *philo) +{ + pthread_mutex_lock(&philo->data->forks[philo->l_fork]); + print_message(philo, "has taken a fork"); + safe_sleep(philo, philo->data->t_die * 1000); + pthread_mutex_unlock(&philo->data->forks[philo->l_fork]); + return (1); +} + +int safe_sleep(t_philo *philo, long time) +{ + long long start_t; + long long target_time; + long sleep_interval; + + start_t = get_time(); + target_time = start_t + (time / 1000); + if (philo->data->nb_philo > 150) + sleep_interval = 400; + else if (philo->data->nb_philo > 100) + sleep_interval = 300; + else if (philo->data->nb_philo > 50) + sleep_interval = 200; + else + sleep_interval = 100; + while (get_time() < target_time) + { + if (check_if_dead(philo)) + return (1); + usleep(sleep_interval); + } + return (0); +} + +int take_fork_2(t_philo *philo) +{ + pthread_mutex_lock(&philo->data->forks[philo->r_fork]); + if (check_if_dead(philo)) + return (pthread_mutex_unlock(&philo->data->forks[philo->r_fork]), 1); + if (print_message(philo, "has taken a fork")) + return (pthread_mutex_unlock(&philo->data->forks[philo->r_fork]), 1); + pthread_mutex_lock(&philo->data->forks[philo->l_fork]); + if (check_if_dead(philo)) + { + pthread_mutex_unlock(&philo->data->forks[philo->l_fork]); + pthread_mutex_unlock(&philo->data->forks[philo->r_fork]); + return (1); + } + return (0); +} + +int take_fork(t_philo *philo) +{ + if (check_if_dead(philo)) + return (1); + if (philo->l_fork < philo->r_fork) + { + pthread_mutex_lock(&philo->data->forks[philo->l_fork]); + if (check_if_dead(philo)) + return (pthread_mutex_unlock + (&philo->data->forks[philo->l_fork]), 1); + if (print_message(philo, "has taken a fork")) + return (pthread_mutex_unlock + (&philo->data->forks[philo->l_fork]), 1); + pthread_mutex_lock(&philo->data->forks[philo->r_fork]); + if (check_if_dead(philo)) + { + pthread_mutex_unlock(&philo->data->forks[philo->r_fork]); + pthread_mutex_unlock(&philo->data->forks[philo->l_fork]); + return (1); + } + } + else + if (take_fork_2(philo)) + return (1); + return (0); +} diff --git a/srcs/routine_utils_2.c b/srcs/routine_utils_2.c new file mode 100644 index 0000000..fddc631 --- /dev/null +++ b/srcs/routine_utils_2.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* routine_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 14:47:26 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 03:59:51 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +void unlock_forks(t_philo *philo) +{ + pthread_mutex_unlock(&philo->data->forks[philo->r_fork]); + pthread_mutex_unlock(&philo->data->forks[philo->l_fork]); +} + +int take_fork_and_eat(t_philo *philo) +{ + long long current_time; + int sleep_result; + + if (check_if_dead(philo)) + return (1); + if (take_fork(philo)) + return (1); + if (print_message(philo, "has taken a fork")) + { + unlock_forks(philo); + return (1); + } + current_time = get_time(); + pthread_mutex_lock(&philo->meal_lock); + philo->last_meal = current_time; + pthread_mutex_unlock(&philo->meal_lock); + if (print_message(philo, "is eating")) + return (unlock_forks(philo), 1); + pthread_mutex_lock(&philo->meal_lock); + philo->m_eaten++; + pthread_mutex_unlock(&philo->meal_lock); + sleep_result = safe_sleep(philo, philo->data->t_eat * 1000); + return (unlock_forks(philo), sleep_result); +} + +int ft_should_continue(t_philo *philo) +{ + if (philo->data->dead_flag) + return (0); + else if (philo->data->must_eat != -1) + { + if (philo->m_eaten >= philo->data->must_eat) + return (0); + else + return (1); + } + else + return (1); +} diff --git a/srcs/threads.c b/srcs/threads.c new file mode 100644 index 0000000..c7ba77b --- /dev/null +++ b/srcs/threads.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* threads.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 15:42:23 by lfirmin #+# #+# */ +/* Updated: 2024/11/22 15:44:44 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +int create_threads(t_data *data) +{ + int i; + pthread_t *threads; + + i = 0; + threads = malloc(sizeof(pthread_t) * data->nb_philo); + if (!threads) + return (1); + while (i < data->nb_philo) + { + if (pthread_create(&data->philos[i].thread, + NULL, &philo_routine, &data->philos[i])) + { + pthread_mutex_lock(&data->dead_mutex); + data->dead_flag = 1; + pthread_mutex_unlock(&data->dead_mutex); + return (free(threads), 1); + } + threads[i] = data->philos[i].thread; + i++; + } + i = 0; + while (i < data->nb_philo) + pthread_join(threads[i++], NULL); + return (free(threads), 0); +} diff --git a/srcs/utils.c b/srcs/utils.c new file mode 100644 index 0000000..5b79204 --- /dev/null +++ b/srcs/utils.c @@ -0,0 +1,104 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/21 17:11:19 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 04:00:00 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +t_data *init_data(void) +{ + t_data *data; + + data = malloc(sizeof(t_data)); + if (!data) + return (NULL); + data->nb_philo = 0; + data->t_die = 0; + data->t_eat = 0; + data->t_sleep = 0; + data->must_eat = -1; + data->dead_flag = 0; + data->forks = NULL; + data->philos = NULL; + data->start_time = 0; + if (pthread_mutex_init(&data->print, NULL)) + return (free(data), NULL); + if (pthread_mutex_init(&data->dead_mutex, NULL)) + return (free(data), NULL); + return (data); +} + +void free_data(t_data *data) +{ + int i; + + if (data) + { + if (data->forks) + { + i = -1; + while (++i < data->nb_philo) + { + pthread_mutex_destroy(&data->forks[i]); + pthread_mutex_destroy(&data->philos[i].meal_lock); + } + free(data->forks); + } + if (data->philos) + free(data->philos); + pthread_mutex_destroy(&data->print); + pthread_mutex_destroy(&data->dead_mutex); + free(data); + } +} + +long long ft_atoll(const char *str) +{ + long long result; + int sign; + + result = 0; + sign = 1; + while (*str == ' ' || (*str >= 9 && *str <= 13)) + str++; + if (*str == '-' || *str == '+') + { + if (*str == '-') + sign = -1; + str++; + } + while (*str >= '0' && *str <= '9') + { + if (result > INT_MAX || result < INT_MIN) + return (2147483648); + result = result * 10 + (*str - '0'); + str++; + } + return (result * sign); +} + +int check_if_dead(t_philo *philo) +{ + int result; + + pthread_mutex_lock(&philo->data->dead_mutex); + result = philo->data->dead_flag; + pthread_mutex_unlock(&philo->data->dead_mutex); + return (result); +} + +int check_if_dead_data(t_data *data) +{ + int result; + + pthread_mutex_lock(&data->dead_mutex); + result = data->dead_flag; + pthread_mutex_unlock(&data->dead_mutex); + return (result); +} diff --git a/srcs/utils_2.c b/srcs/utils_2.c new file mode 100644 index 0000000..9633306 --- /dev/null +++ b/srcs/utils_2.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils_2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/22 14:20:46 by lfirmin #+# #+# */ +/* Updated: 2025/03/17 04:00:06 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "../include/philo.h" + +long long get_time(void) +{ + struct timeval time; + + if (gettimeofday(&time, NULL) == -1) + return (write(2, "gettimeofday() error\n", 22), 0); + return ((time.tv_sec * 1000) + (time.tv_usec / 1000)); +} + +int print_message(t_philo *philo, char *message) +{ + int is_dead; + + pthread_mutex_lock(&philo->data->dead_mutex); + is_dead = philo->data->dead_flag; + pthread_mutex_unlock(&philo->data->dead_mutex); + if (is_dead) + return (1); + if (pthread_mutex_lock(&philo->data->print) != 0) + return (1); + pthread_mutex_lock(&philo->data->dead_mutex); + is_dead = philo->data->dead_flag; + pthread_mutex_unlock(&philo->data->dead_mutex); + if (is_dead) + return (pthread_mutex_unlock(&philo->data->print), 1); + printf("%lld %lld %s\n", get_time() + - philo->data->start_time, philo->id, message); + pthread_mutex_unlock(&philo->data->print); + return (0); +}