commit cde3e458fe13a4b02e8944781b8b97edf07e4e57 Author: Raphaƫl <35407363+EniumRaphael@users.noreply.github.com> Date: Tue Jun 25 17:04:47 2024 +0200 Add files via upload diff --git a/philo/Makefile b/philo/Makefile new file mode 100644 index 0000000..64f3128 --- /dev/null +++ b/philo/Makefile @@ -0,0 +1,122 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: rparodi +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2023/11/12 11:05:05 by rparodi #+# #+# # +# Updated: 2024/06/16 12:23:39 by rparodi ### ########.fr # +# # +# **************************************************************************** # + + +# Variables + +# Name +NAME = philo + +# Commands +CC = cc +RM = rm -rf + +# Flags +CFLAGS = -Werror -Wextra -Wall -Wno-unused-command-line-argument -g3 -MMD + +INCLUDES = ./includes/philo.h \ + ./includes/types.h + +SRC = ./sources/ft_atou.c \ + ./sources/ft_exit.c \ + ./sources/main.c \ + ./sources/parsing_args.c \ + ./sources/routine.c \ + ./sources/ft_actions.c + +# Objects +OBJDIRNAME = ./objects +OBJ = $(addprefix $(OBJDIRNAME)/,$(SRC:.c=.o)) + +# Colors +GREEN = \033[32m +GREY = \033[0;90m +RED = \033[0;31m +GOLD = \033[38;5;220m +END = \033[0m + +# Rules + +# All (make all) +all: header $(NAME) footer + +# Bonus (make bonus) +bonus: header $(OBJ) $(LIB_OBJ) footer + @mkdir -p $(OBJDIRNAME) + @mkdir -p $(OBJDIRNAME)/$(SRCDIRNAME) + @printf '$(GREY) Creating $(END)$(GREEN)$(OBJDIRNAME)$(END)\n' + @printf '$(GREY) Be Carefull ur in $(END)$(GREEN)Debug Mode$(END)\n' + @cc $(CFLAGS) -D DEBUG=42 -o $(NAME) $(OBJ) $(LIB_OBJ) + +# Clean (make clean) +clean: + @printf '$(GREY) Removing $(END)$(RED)Objects$(END)\n' + @printf '$(GREY) Removing $(END)$(RED)Objects Folder$(END)\n' + @$(RM) $(OBJDIRNAME) + +# Clean (make fclean) +fclean: clean + @printf '$(GREY) Removing $(END)$(RED)Program$(END)\n' + @$(RM) $(NAME) + @echo "" + +# Restart (make re) +re: header fclean all + +# Dependences for all +$(NAME): $(OBJ) + @mkdir -p $(OBJDIRNAME) + @mkdir -p $(OBJDIRNAME)/$(SRCDIRNAME) + @printf '$(GREY) Creating $(END)$(GREEN)$(OBJDIRNAME)$(END)\n' + @cc $(CFLAGS) -o $(NAME) $(OBJ) + +# Creating the objects +$(OBJDIRNAME)/%.o: %.c + @mkdir -p $(dir $@) + @printf '$(GREY) Compiling $(END)$(GREEN)$<$(END)\n' + @cc $(CFLAGS) -o $@ -c $< + +# Header +header: + @clear + @printf '\n\n' + @printf '$(GOLD) ******* ****** ******* $(END)\n' + @printf '$(GOLD) ****** *** ******* $(END)\n' + @printf '$(GOLD) ******* * ******* $(END)\n' + @printf '$(GOLD) ****** ******* $(END)\n' + @printf '$(GOLD) ******* ******* $(END)\n' + @printf '$(GOLD) ******************* ******* * $(END)\n' + @printf '$(GOLD) ******************* ******* *** $(END)\n' + @printf '$(GOLD) ****** ******* ****** $(END)\n' + @printf '$(GOLD) ****** $(END)\n' + @printf '$(GOLD) ****** $(END)\n' + @printf '$(GREY) Made by rparodi$(END)\n\n' + +# Footer +footer: + @printf "\n" + @printf "$(GOLD) ,_ _,$(END)\n" + @printf "$(GOLD) | \\___//|$(END)\n" + @printf "$(GOLD) |=6 6=|$(END)\n" + @printf "$(GOLD) \\=._Y_.=/$(END)\n" + @printf "$(GOLD) ) \` ( ,$(END)\n" + @printf "$(GOLD) / \\ (('$(END)\n" + @printf "$(GOLD) | | ))$(END)\n" + @printf "$(GOLD) /| | | |\\_//$(END)\n" + @printf "$(GOLD) \\| |._.| |/-\`$(END)\n" + @printf "$(GOLD) '\"' '\"'$(END)\n" + @printf ' $(GREY)The compilation is$(END) $(GOLD)finish$(END)\n $(GREY)Have a good $(END)$(GOLD)correction !$(END)\n' + +# Phony +.PHONY: all bonus clean fclean re + +-include ${OBJ:.o=.d} diff --git a/philo/includes/philo.h b/philo/includes/philo.h new file mode 100644 index 0000000..4081e98 --- /dev/null +++ b/philo/includes/philo.h @@ -0,0 +1,93 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/04 11:34:04 by rparodi #+# #+# */ +/* Updated: 2024/06/17 14:12:53 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PHILO_H +# define PHILO_H + +# include +# include +# include +# include +# include +# include +# include +# include +# include "./types.h" + +# define ARGS "Usage: ./philo ()" + +# define GREEN "\033[32m" +# define GREY "\033[0;90m" +# define RED "\033[0;31m" +# define BLUE "\033[34m" +# define GOLD "\033[38;5;220m" +# define END "\033[0m" + +# ifndef MAXSUPPORT +# define MAXSUPPORT 200 +# endif + +# ifndef EATTIME +# define EATTIME 3 +# endif + +typedef struct s_philo +{ + t_usize nb_philo; + t_usize t_eat; + t_usize t_death; + t_usize t_sleep; + t_i32 nb_eat; + pthread_t thread; + t_i32 id; + t_i32 eating; + t_i32 eating_count; + t_usize t_last_eat; + t_usize start_time; + t_i32 *dead_check; + t_mutex *r_fork; + t_mutex *l_fork; + t_mutex *print_lock; + t_mutex *dead_lock; + t_mutex *meal_lock; +} t_philo; + +typedef struct s_program +{ + t_i32 dead_flag; + t_mutex dead_lock; + t_mutex meal_lock; + t_mutex print_lock; + t_philo *philos; +} t_program; + +t_usize ft_time(void); +void ft_free(void *ptr); +t_usize ft_atou_return(t_str str); +t_error ft_sleeping(t_philo *philo); +t_error ft_thinking(t_philo *philo); +t_i32 main(t_i32 argc, t_str *argv); +void ft_pause(size_t milliseconds); +t_error ft_start_eating(t_philo *philo); +void ft_exit(t_str msg, t_u8 status); +t_error ft_ending_eating(t_philo *philo); +void ft_logs(t_str msg, t_philo *philo); +t_error ft_atou(const char *nptr, t_usize *value); +t_error ft_init_fork(t_philo *philo, t_mutex *fork); +t_error ft_init_thread(t_program *prog, t_mutex *forks); +t_error ft_parsing_args(t_i32 argc, t_str *argv, t_philo *philo); +t_error ft_init(int argc, t_str *argv, t_program *program, t_philo *philo); +t_error ft_init_philo(t_i32 argc, t_str *argv, t_program *prog, t_mutex *forks); +void ft_destroy_exit(t_str msg, t_u8 status, t_program *prog, \ + t_mutex *forks); + +#endif diff --git a/philo/includes/types.h b/philo/includes/types.h new file mode 100644 index 0000000..90a53f0 --- /dev/null +++ b/philo/includes/types.h @@ -0,0 +1,72 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* types.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/03 14:31:12 by maiboyer #+# #+# */ +/* Updated: 2024/06/09 14:32:57 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef TYPES_H +# define TYPES_H + +# include +# include +# include +# include +# include + +/// @def signal that an error occured +# define ERROR 1 +/// @def signal that no error occured +# define NO_ERROR 0 + +/// @brief A mutex (using pthread) +typedef pthread_mutex_t t_mutex; +// @brief A thread (using pthread) +typedef pthread_t t_thread; + +/// @brief A string, null terminated +typedef char *t_str; +/// @brief A constant string, null terminated +typedef const char *t_const_str; + +/// @brief an unsigned 8 bit integer +typedef uint8_t t_u8; +/// @brief a signed 8 bit integer +typedef int8_t t_i8; + +/// @brief an unsigned 16 bit integer +typedef uint16_t t_u16; +/// @brief a signed 16 bit integer +typedef int16_t t_i16; + +/// @brief an unsigned 32 bit integer +typedef uint32_t t_u32; +/// @brief a signed 32 bit integer +typedef int32_t t_i32; + +/// @brief an unsigned 64 bit integer +typedef uint64_t t_u64; +/// @brief a signed 64 bit integer +typedef int64_t t_i64; + +/// @brief a signed integer that can hold a pointer +typedef ssize_t t_isize; +/// @brief an unsigned integer that can hold a pointer +typedef size_t t_usize; + +/// @brief a 32 bit floating point number +typedef float t_f32; +/// @brief a 64 bit floating point number +typedef double t_f64; + +/// @brief a boolean value that represents an error +/// @note true is an error, false is no error +typedef bool t_error; +typedef bool t_bool; + +#endif diff --git a/philo/sources/ft_actions.c b/philo/sources/ft_actions.c new file mode 100644 index 0000000..187491d --- /dev/null +++ b/philo/sources/ft_actions.c @@ -0,0 +1,63 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_actions.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/10 00:23:09 by rparodi #+# #+# */ +/* Updated: 2024/06/18 15:50:49 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/philo.h" + +void ft_logs(t_str msg, t_philo *philo) +{ + const t_usize time = ft_time() - philo->start_time; + + if (msg != NULL) + printf("%s%zu %s%i %s%s%s", BLUE, time, GOLD, philo->id, GREEN, msg, END); +} + +t_error ft_thinking(t_philo *philo) +{ + ft_logs("is thinking\n", philo); + return (NO_ERROR); +} + +t_error ft_start_eating(t_philo *philo) +{ + const t_usize time = ft_time() - philo->start_time; + + if (philo->id % 2 == 0) + { + pthread_mutex_lock(philo->l_fork); + ft_logs("has taken a fork\n", philo); + pthread_mutex_lock(philo->r_fork); + ft_logs("has taken a fork\n", philo); + } + else + { + pthread_mutex_lock(philo->r_fork); + ft_logs("has taken a fork\n", philo); + pthread_mutex_lock(philo->l_fork); + ft_logs("has taken a fork\n", philo); + } + philo->eating = true; + ft_logs("is eating\n", philo); + philo->t_last_eat = time; + philo->eating_count++; + ft_pause(EATTIME * 1000); + pthread_mutex_unlock(philo->r_fork); + pthread_mutex_unlock(philo->l_fork); + philo->eating = false; + return (NO_ERROR); +} + +t_error ft_sleeping(t_philo *philo) +{ + ft_logs("is sleeping\n", philo); + ft_pause(philo->t_sleep); + return (NO_ERROR); +} diff --git a/philo/sources/ft_atou.c b/philo/sources/ft_atou.c new file mode 100644 index 0000000..e52612e --- /dev/null +++ b/philo/sources/ft_atou.c @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atou.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/09 16:27:52 by rparodi #+# #+# */ +/* Updated: 2024/06/09 18:27:02 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/philo.h" + +static t_i32 ft_check_space(t_i32 c) +{ + if (c == 32 || (c >= 9 && c <= 13)) + return (1); + return (0); +} + +static t_i32 ft_check_sign(const char *nptr, t_i32 *i) +{ + while (ft_check_space(nptr[*i])) + (*i)++; + if (nptr[*i] == '-') + { + (*i)++; + return (-1); + } + else if (nptr[*i] == '+') + (*i)++; + return (1); +} + +t_error ft_atou(const char *nptr, t_usize *value) +{ + t_i32 i; + t_i32 sign; + + i = 0; + sign = ft_check_sign(nptr, &i); + (*value) = 0; + if (sign != 1) + ft_exit("Negative number if find !\n", ERROR); + while (nptr[i]) + { + if (nptr[i] >= '0' && nptr[i] <= '9') + (*value) = ((*value) * 10) + nptr[i] - '0'; + else + break ; + i++; + } + return (NO_ERROR); +} + +t_usize ft_atou_return(t_str str) +{ + t_usize number; + + number = 0; + ft_atou(str, &number); + return (number); +} diff --git a/philo/sources/ft_exit.c b/philo/sources/ft_exit.c new file mode 100644 index 0000000..bea6e5f --- /dev/null +++ b/philo/sources/ft_exit.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_exit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/04 12:23:50 by rparodi #+# #+# */ +/* Updated: 2024/06/17 12:38:01 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/philo.h" + +t_usize ft_strlen(t_str str) +{ + t_usize i; + + i = 0; + while (str[i] != '\0') + i++; + return (i); +} + +void ft_putchar_fd(t_i32 fd, t_str str) +{ + if (str != NULL) + write(fd, str, ft_strlen(str)); +} + +void ft_free(void *ptr) +{ + if (ptr != NULL) + { + free(ptr); + ptr = NULL; + } +} + +void ft_exit(t_str msg, t_u8 status) +{ + ft_putchar_fd(status + 1, msg); + exit(status); +} + +void ft_destroy_exit(t_str msg, t_u8 status, t_program *prog, t_mutex *forks) +{ + t_usize i; + + i = 0; + pthread_mutex_destroy(&prog->print_lock); + pthread_mutex_destroy(&prog->meal_lock); + pthread_mutex_destroy(&prog->dead_lock); + while (i < prog->philos[0].nb_philo) + { + pthread_mutex_destroy(&forks[i]); + i++; + } + ft_exit(msg, status); +} diff --git a/philo/sources/main.c b/philo/sources/main.c new file mode 100644 index 0000000..825ce32 --- /dev/null +++ b/philo/sources/main.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/04 11:30:25 by rparodi #+# #+# */ +/* Updated: 2024/06/16 12:22:40 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/philo.h" + +t_i32 main(t_i32 argc, t_str *argv) +{ + t_philo philo[MAXSUPPORT]; + t_program prog; + + if (argc != 6 && argc != 5) + ft_exit(ARGS, 1); + if (ft_init(argc, argv, &prog, philo)) + ft_exit("Issues during initialisation\n", ERROR); + return (0); +} diff --git a/philo/sources/parsing_args.c b/philo/sources/parsing_args.c new file mode 100644 index 0000000..496df83 --- /dev/null +++ b/philo/sources/parsing_args.c @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parsing_args.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/04 11:42:37 by rparodi #+# #+# */ +/* Updated: 2024/06/18 15:09:06 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/philo.h" + +t_error ft_parsing_args(t_i32 argc, t_str *argv, t_philo *philo) +{ + t_usize tmp; + + tmp = 0; + if (argc == 6) + { + ft_atou(argv[5], &tmp); + philo->nb_eat = tmp; + } + else + philo->t_eat = -1; + ft_atou(argv[1], &tmp); + philo->nb_philo = tmp; + ft_atou(argv[2], &tmp); + philo->t_death = tmp; + ft_atou(argv[3], &tmp); + philo->t_eat = tmp; + ft_atou(argv[4], &tmp); + philo->t_sleep = tmp; + return (NO_ERROR); +} + +t_error ft_init_fork(t_philo *philo, t_mutex *fork) +{ + t_usize i; + + i = 0; + while (i < philo->nb_philo) + { + pthread_mutex_init(&fork[i], NULL); + i++; + } + return (NO_ERROR); +} + +t_usize ft_time(void) +{ + struct timeval time; + + if (gettimeofday(&time, NULL) == -1) + ft_exit("Error of during ft_time !\n", 1); + return (time.tv_sec * 1000 + time.tv_usec / 1000); +} + +void ft_pause(size_t milliseconds) +{ + const t_usize start = ft_time(); + + while ((ft_time() - start) < milliseconds) + usleep(500); +} + +t_error ft_init_philo(t_i32 argc, t_str *argv, t_program *prog, t_mutex *forks) +{ + t_usize i; + + i = 0; + while (i < ft_atou_return(argv[1])) + { + prog->philos[i].id = i + 1; + prog->philos[i].eating = 0; + ft_parsing_args(argc, argv, &prog->philos[i]); + prog->philos[i].start_time = ft_time(); + prog->philos[i].t_last_eat = ft_time(); + prog->philos[i].print_lock = &prog->print_lock; + prog->philos[i].dead_lock = &prog->dead_lock; + prog->philos[i].meal_lock = &prog->meal_lock; + prog->philos[i].dead_check = &prog->dead_flag; + prog->philos[i].l_fork = &forks[i]; + if (i == 0) + prog->philos[i].r_fork = &forks[prog->philos[i].nb_philo - 1]; + else + prog->philos[i].r_fork = &forks[i - 1]; + i++; + } + if (ft_parsing_args(argc, argv, prog->philos)) + return (ERROR); + return (NO_ERROR); +} + +t_error ft_init(t_i32 argc, t_str *argv, t_program *prog, t_philo *philo) +{ + static t_mutex forks[MAXSUPPORT] = { 0 }; + + pthread_mutex_init(&prog->print_lock, NULL); + pthread_mutex_init(&prog->dead_lock, NULL); + pthread_mutex_init(&prog->meal_lock, NULL); + prog->philos = philo; + prog->dead_flag = 0; + if (ft_init_philo(argc, argv, prog, forks)) + return (ERROR); + if (philo->nb_philo != 0 && philo->nb_philo > MAXSUPPORT) + return (ERROR); + ft_init_thread(prog, forks); + return (NO_ERROR); +} diff --git a/philo/sources/routine.c b/philo/sources/routine.c new file mode 100644 index 0000000..689f46f --- /dev/null +++ b/philo/sources/routine.c @@ -0,0 +1,112 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* routine.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/11 11:42:31 by rparodi #+# #+# */ +/* Updated: 2024/06/20 15:04:13 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/philo.h" + +t_bool dead_loop(t_philo *philo) +{ + pthread_mutex_lock(philo->dead_lock); + if (*philo->dead_check == true) + return (pthread_mutex_unlock(philo->dead_lock), true); + pthread_mutex_unlock(philo->dead_lock); + return (false); +} + +t_bool check_dead(t_philo *philo) +{ + t_usize i; + + i = 0; + while (i < philo[0].nb_philo) + { + if (ft_time() - philo[i].t_last_eat > philo[i].t_eat) + return (true); + } + i++; + return (false); +} + +t_bool check_eat(t_philo *philo) +{ + t_usize i; + t_u8 check; + + i = 0; + check = 0; + if (philo[0].nb_eat == -1) + return (false); + while (i < philo[0].nb_philo) + { + if (philo[i].eating_count >= philo[i].nb_eat) + check++; + i++; + } + if (check == philo[0].nb_philo) + return (true); + return (false); +} + +void *ft_watch_dogs(void *ptr) +{ + t_philo *philo; + + philo = (t_philo *) ptr; + if (philo == NULL) + return (NULL); + while (true) + { + if (check_dead(philo)) + break ; + if (check_eat(philo)) + break ; + } + return (philo); +} + +void *ft_routine(void *ptr) +{ + t_philo *philo; + + philo = (t_philo *) ptr; + if (philo == NULL) + return (NULL); + while (!dead_loop(philo)) + { + ft_start_eating(philo); + ft_sleeping(philo); + ft_thinking(philo); + } + return (philo); +} + +t_error ft_init_thread(t_program *prog, t_mutex *forks) +{ + t_thread o_block; + t_usize i; + + i = 0; + if (pthread_create(&o_block, NULL, &ft_watch_dogs, prog->philos)) + ft_destroy_exit("Allocation of watch_dogs failed\n", \ + ERROR, prog, forks); + while (i < prog->philos[0].nb_philo) + { + if (pthread_create(&prog->philos[i].thread, NULL, &ft_routine, \ + &prog->philos[i])) + ft_destroy_exit("Allocation of one philo thread failed !\n", \ + ERROR, prog, forks); + i++; + } + pthread_join(o_block, NULL); + while (--i > 0) + pthread_join(prog->philos[i].thread, NULL); + return (NO_ERROR); +} diff --git a/philo/test.c b/philo/test.c new file mode 100644 index 0000000..3181d44 --- /dev/null +++ b/philo/test.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/09 15:08:23 by rparodi #+# #+# */ +/* Updated: 2024/06/17 12:24:16 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include +#include +#include +#include + +// printf derriere un mutex pour le printf +// zero printf apres une mort +// mort shared avec un mutex +// compte le nombre de ois manger par philo, et chec via un thread si tous a manger X fois + +pthread_t philosopher[15]; +pthread_mutex_t chopstick[15]; + +int ft_sleep(size_t milliseconds) +{ + struct timeval start; + struct timeval tempo; + + gettimeofday(&tempo, NULL); + gettimeofday(&start, NULL); + while ((tempo - start) < milliseconds) + { + usleep(500); + gettimeofday(&tempo, NULL); + } + return (0); +} + +void *func(void *arg) { + int n = *((int *)arg); + printf("Philosopher %d is thinking\n", n); + + pthread_mutex_lock(&chopstick[n]); + pthread_mutex_lock(&chopstick[(n + 1) % 15]); + printf("Philosopher %d is eating\n", n); + ft_sleep(3000000); // sleep for 3 seconds to simulate eating + pthread_mutex_unlock(&chopstick[n]); + pthread_mutex_unlock(&chopstick[(n + 1) % 15]); + printf("Philosopher %d finished eating\n", n); + + free(arg); // Free the allocated memory + return NULL; +} + +int main() { + int i; + + for (i = 0; i < 15; i++) + pthread_mutex_init(&chopstick[i], NULL); + + for (i = 0; i < 15; i++) { + int *arg = malloc(sizeof(*arg)); + if (arg == NULL) { + fprintf(stderr, "Couldn't allocate memory for thread arg.\n"); + exit(EXIT_FAILURE); + } + *arg = i; + pthread_create(&philosopher[i], NULL, func, arg); + } + + for (i = 0; i < 15; i++) + pthread_join(philosopher[i], NULL); + + for (i = 0; i < 15; i++) + pthread_mutex_destroy(&chopstick[i]); + + return 0; +} +