From a37cbf88f3a1b3a78ea10cb4a957c6c211f2bc77 Mon Sep 17 00:00:00 2001 From: Camille Chauvet Date: Thu, 13 Apr 2023 13:00:39 +0000 Subject: [PATCH] init --- Makefile | 37 +++++++++++++++ data.c | 41 +++++++++++++++++ data.h | 5 +++ main.c | 91 +++++++++++++++++++++++++++++++++++++ parsing.c | 48 ++++++++++++++++++++ parsing.h | 4 ++ philo.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ philo.h | 22 +++++++++ philos.c | 39 ++++++++++++++++ philos.h | 5 +++ print.c | 41 +++++++++++++++++ print.h | 7 +++ struct.h | 38 ++++++++++++++++ threads.c | 20 +++++++++ threads.h | 6 +++ time.c | 17 +++++++ time.h | 3 ++ utils/ft_atoi.c | 39 ++++++++++++++++ utils/ft_isnum.c | 27 +++++++++++ utils/utils.h | 21 +++++++++ 20 files changed, 625 insertions(+) create mode 100644 Makefile create mode 100644 data.c create mode 100644 data.h create mode 100644 main.c create mode 100644 parsing.c create mode 100644 parsing.h create mode 100644 philo.c create mode 100644 philo.h create mode 100644 philos.c create mode 100644 philos.h create mode 100644 print.c create mode 100644 print.h create mode 100644 struct.h create mode 100644 threads.c create mode 100644 threads.h create mode 100644 time.c create mode 100644 time.h create mode 100644 utils/ft_atoi.c create mode 100644 utils/ft_isnum.c create mode 100644 utils/utils.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..10ee4b8 --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +SRCS = parsing.c \ + utils/ft_isnum.c \ + utils/ft_atoi.c \ + main.c \ + time.c \ + print.c \ + data.c \ + philo.c \ + philos.c \ + threads.c + +OBJS = ${SRCS:.c=.o} + +NAME = philo + +CC = clang + +FLAGS = -Wall -Wextra -Werror -g + +%.o: %.c + ${CC} ${FLAGS} -c -o $@ $< + +${NAME}: ${OBJS} + ${CC} ${OBJS} -o ${NAME} + +all: ${NAME} + +clean: + rm -f ${OBJS} + +fclean: clean + rm -f ${NAME} + +re: fclean + make all + +.PHONY: all clean fclean re diff --git a/data.c b/data.c new file mode 100644 index 0000000..9573ec1 --- /dev/null +++ b/data.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include "./data.h" +#include "philo.h" +#include "philos.h" +#include "struct.h" + +bool data_init(t_data *data) +{ + data->forks = malloc(sizeof(bool) * data->nb_philos); + if (data->forks == NULL) + return (1); + data->philos = malloc(sizeof(t_philo) * data->nb_philos); + if (data->philos == NULL) + { + free(data->forks); + return (1); + } + data->threads = malloc(sizeof(pthread_t) * data->nb_philos); + if (data->forks == NULL) + { + free(data->philos); + free(data->forks); + return (1); + } + data->stop = 0; + data->nb_meals = 0; + return (0); +} + +void data_destroyer(t_data *data) +{ + free(data->threads); + free(data->forks); + pthread_mutex_destroy(&data->nb_meal_mutex); + pthread_mutex_destroy(&data->forks_mutex); + pthread_mutex_destroy(&data->stop_mutex); + philos_destroyer(data); +} diff --git a/data.h b/data.h new file mode 100644 index 0000000..1f5604c --- /dev/null +++ b/data.h @@ -0,0 +1,5 @@ +# include "./struct.h" + +bool data_init(t_data *data); +void data_destroyer(t_data *data); + diff --git a/main.c b/main.c new file mode 100644 index 0000000..a2b15f8 --- /dev/null +++ b/main.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include "./philos.h" +#include "./data.h" +#include "./parsing.h" +#include "./threads.h" +#include "./time.h" +#include "./print.h" +#include "./struct.h" + +size_t get_min_meal(t_data *data) +{ + size_t i; + size_t min; + size_t value; + t_philo *philo; + + philo = data->philos[0]; + min = philo->nb_meal; + i = 1; + while (i < data->nb_philos) + { + philo = data->philos[i]; + pthread_mutex_lock(&philo->nb_meal_mutex); + value = philo->nb_meal; + pthread_mutex_unlock(&philo->nb_meal_mutex); + if (min > value) + min = value; + i++; + } + return (min); +} + +void stop(t_data *data) +{ + pthread_mutex_lock(&data->stop_mutex); + data->stop = 1; + pthread_mutex_unlock(&data->stop_mutex); +} + +void check_routine(t_data *data) +{ + size_t i; + bool ok; + t_philo *philo; + + while (true) + { + if ((ssize_t) get_min_meal(data) == data->nb_meals) + stop(data); + + i = 0; + while (i < data->nb_philos) + { + philo = data->philos[i]; + pthread_mutex_lock(&philo->last_eat_mutex); + ok = !(philo->last_eat + data->life_expectency > get_time()); + pthread_mutex_unlock(&philo->last_eat_mutex); + if (ok == 1) + { + print_died(philo); + return ; + } + i++; + } + } +} + +int main(int ac, char **av) +{ + t_data data; + + if (parsing(&data, av + 1, ac - 1)) + return (1); + if (data_init(&data)) + return (1); + if (philos_init(&data)) + { + data_destroyer(&data); + return (1); + } + if (threads_init(&data)) + { + data_destroyer(&data); + return (1); + } + check_routine(&data); + data_destroyer(&data); +} diff --git a/parsing.c b/parsing.c new file mode 100644 index 0000000..773fd55 --- /dev/null +++ b/parsing.c @@ -0,0 +1,48 @@ +#include "utils/utils.h" +#include "./data.h" +#include +#include +#include + +static bool check_amount_of_argument(size_t n) +{ + return (n < 4 || n > 5); +} + +static bool check_value(char **av, size_t n) +{ + size_t i; + + i = 0; + while (i < n) + { + if (ft_isnum(av[i]) == 0) + return (1); + i++; + } + return (0); +} + +static void set_value(t_data *data, char **args, size_t n) +{ + data->nb_philos = ft_atoi(args[0]); + data->life_expectency = ft_atoi(args[1]); + data->eat_time = ft_atoi(args[2]); + data->sleep_time = ft_atoi(args[3]); + if (n == 5) + data->nb_meals = ft_atoi(args[4]); + else + data->nb_meals = -1; +} + +bool parsing(t_data *data, char **args, size_t n) +{ + if (check_amount_of_argument(n) + || check_value(args, n)) + { + write(2, "Argument error !\n", 16); + return (1); + } + set_value(data, args, n); + return (0); +} diff --git a/parsing.h b/parsing.h new file mode 100644 index 0000000..b817f98 --- /dev/null +++ b/parsing.h @@ -0,0 +1,4 @@ +#include "./data.h" + +bool parsing(t_data *data, char **args, size_t n); + diff --git a/philo.c b/philo.c new file mode 100644 index 0000000..f574fbc --- /dev/null +++ b/philo.c @@ -0,0 +1,114 @@ +#include "philo.h" +#include "struct.h" +#include "time.h" +#include "data.h" +#include +#include +#include +#include "./print.h" + +void philo_destroyer(t_philo *philo) +{ + pthread_mutex_destroy(&philo->nb_meal_mutex); + pthread_mutex_destroy(&philo->last_sleep_mutex); + pthread_mutex_destroy(&philo->last_eat_mutex); + free(philo); +} + +bool check(t_data *data) +{ + bool stop; + + pthread_mutex_lock(&data->stop_mutex); + stop = data->stop; + pthread_mutex_unlock(&data->stop_mutex); + return (stop); +} + +void eat(t_philo *philo, t_data *data) +{ + print_take_a_fork(philo); + print_take_a_fork(philo); + print_eating(philo); + usleep(data->eat_time * 1000); + pthread_mutex_lock(&philo->nb_meal_mutex); + philo->nb_meal++; + pthread_mutex_unlock(&philo->nb_meal_mutex); + pthread_mutex_lock(&data->forks_mutex); + data->forks[philo->id] = 1; + data->forks[(philo->id + 1) % (data->nb_philos) + 1] = 1; + pthread_mutex_unlock(&data->forks_mutex); +} + +bool philo_eat(t_philo *philo, t_data *data) +{ + bool left_fork; + bool right_fork; + + left_fork = 0; + right_fork = 0; + while (left_fork == 0 || right_fork == 0) + { + if (check(data)) + return (1); + pthread_mutex_lock(&data->forks_mutex); + left_fork = data->forks[philo->id]; + right_fork = data->forks[(philo->id + 1) % (data->nb_philos) + 1]; + if (right_fork && left_fork) + { + data->forks[philo->id] = !left_fork; + data->forks[(philo->id + 1) % (data->nb_philos) + 1] = !right_fork; + } + pthread_mutex_unlock(&data->forks_mutex); + } + eat(philo, data); + pthread_mutex_lock(&philo->last_eat_mutex); + philo->last_eat = get_time(); + pthread_mutex_unlock(&philo->last_eat_mutex); + return (0); +} + +void philo_sleep(t_data *data, t_philo *philo) +{ + print_sleeping(philo); + usleep(data->sleep_time * 1000); +} + + +void *philo_routine(void *arg) +{ + t_philo *philo; + t_data *data; + + philo = arg; + data = philo->data; + while (true) + { + print_thinking(philo); + check(data); + philo_eat(philo, data); + check(data); + print_thinking(philo); + if (check(data)) + return (NULL); + philo_sleep(data, philo); + } + return (NULL); +} + +t_philo *philo_init(t_data *data) +{ + t_philo *philo; + static size_t id = 0; + + philo = malloc(sizeof(t_philo)); + if (philo == NULL) + return (NULL); + philo->id = id++; + philo->data = data; + philo->nb_meal = 0; + pthread_mutex_init(&philo->nb_meal_mutex, NULL); + pthread_mutex_init(&philo->nb_meal_mutex, NULL); + pthread_mutex_init(&philo->nb_meal_mutex, NULL); + return (philo); +} diff --git a/philo.h b/philo.h new file mode 100644 index 0000000..7450b4e --- /dev/null +++ b/philo.h @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cchauvet +# include +# include +# include +# include "./data.h" + +t_philo *philo_init(t_data *data); +void philo_destroyer(t_philo *philo); +void *philo_routine(void *arg); + diff --git a/philos.c b/philos.c new file mode 100644 index 0000000..5708861 --- /dev/null +++ b/philos.c @@ -0,0 +1,39 @@ +#include "./philo.h" +#include "struct.h" +#include +#include + +int philos_init(t_data *data) +{ + size_t i; + + i = 0; + while (i < data->nb_philos) + { + data->philos[i] = philo_init(data); + if (data->philos[i] == NULL) + { + while (i > 0) + { + philo_destroyer(data->philos[i]); + i--; + } + return (1); + } + i++; + } + return (0); +} + +void philos_destroyer(t_data *data) +{ + size_t i; + + i = 0; + while (i < data->nb_philos) + { + philo_destroyer(data->philos[i]); + i++; + } + free(data->philos); +} diff --git a/philos.h b/philos.h new file mode 100644 index 0000000..1be6aa0 --- /dev/null +++ b/philos.h @@ -0,0 +1,5 @@ +# include +# include "./data.h" + +bool philos_init(t_data *data); +void philos_destroyer(t_data *data); diff --git a/print.c b/print.c new file mode 100644 index 0000000..f1a9904 --- /dev/null +++ b/print.c @@ -0,0 +1,41 @@ +#include "philo.h" +#include +#include +#include +#include "./time.h" + +static void print(size_t id, char *str) +{ + static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER; + size_t time; + + time = get_time(); + pthread_mutex_lock(&print_mutex); + printf("%zu %zu %s\n", time, id, str); + pthread_mutex_unlock(&print_mutex); +} + +void print_take_a_fork(t_philo *philo) +{ + print(philo->id, "has taken a fork"); +} + +void print_eating(t_philo *philo) +{ + print(philo->id, "is eating"); +} + +void print_sleeping(t_philo *philo) +{ + print(philo->id, "is sleeping"); +} + +void print_thinking(t_philo *philo) +{ + print(philo->id, "is thinking"); +} + +void print_died(t_philo *philo) +{ + print(philo->id, "is died"); +} diff --git a/print.h b/print.h new file mode 100644 index 0000000..313fdbb --- /dev/null +++ b/print.h @@ -0,0 +1,7 @@ +# include "./philo.h" + +void print_eating(t_philo *philo); +void print_take_a_fork(t_philo *philo); +void print_sleeping(t_philo *philo); +void print_thinking(t_philo *philo); +void print_died(t_philo *philo); diff --git a/struct.h b/struct.h new file mode 100644 index 0000000..d42783f --- /dev/null +++ b/struct.h @@ -0,0 +1,38 @@ +#ifndef STRUCT_H +# define STRUCT_H +# include +# include +# include + +typedef struct s_data +{ + size_t eat_time; + size_t sleep_time; + size_t life_expectency; + size_t nb_philos; + ssize_t nb_meals; + void **philos; + pthread_t *threads; + pthread_mutex_t forks_mutex; + bool *forks; + pthread_mutex_t stop_mutex; + bool stop; +} t_data; + +typedef struct s_philo +{ + size_t id; + pthread_mutex_t nb_meal_mutex; + size_t nb_meal; + pthread_mutex_t last_eat_mutex; + size_t last_eat; + pthread_mutex_t last_sleep_mutex; + size_t last_sleep; + t_data *data; +} t_philo; + +t_philo *philo_create(t_data *data); +t_philo *philo_destoyer(t_philo *philo); +void *philo_routine(void *arg); + +#endif diff --git a/threads.c b/threads.c new file mode 100644 index 0000000..1677d9c --- /dev/null +++ b/threads.c @@ -0,0 +1,20 @@ +#include "philo.h" +#include "struct.h" +#include +#include +#include + +bool threads_init(t_data *data) +{ + size_t i; + + i = 0; + while (i < data->nb_philos) + { + if (pthread_create(&data->threads[i], NULL, philo_routine, data->philos[i])) + return (true); + pthread_detach(data->threads[i]); + i++; + } + return (false); +} diff --git a/threads.h b/threads.h new file mode 100644 index 0000000..4d14787 --- /dev/null +++ b/threads.h @@ -0,0 +1,6 @@ +# include "./data.h" +#include "struct.h" +# include + +bool threads_init(t_data *data); + diff --git a/time.c b/time.c new file mode 100644 index 0000000..b1b8cb7 --- /dev/null +++ b/time.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +size_t get_time(void) +{ + size_t timedefault = 0; + size_t time; + struct timeval tv; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000000 + tv.tv_usec; + if (timedefault == 0) + timedefault = time; + return ((time - timedefault) / 1000); +} diff --git a/time.h b/time.h new file mode 100644 index 0000000..c8c4cef --- /dev/null +++ b/time.h @@ -0,0 +1,3 @@ +# include + +size_t get_time(void); diff --git a/utils/ft_atoi.c b/utils/ft_atoi.c new file mode 100644 index 0000000..e8b20c1 --- /dev/null +++ b/utils/ft_atoi.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atoi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cchauvet + +int ft_atoi(const char *str) +{ + int out; + char sign; + size_t i; + + sign = 1; + i = 0; + while (str[i] == '-' || str[i]== '+') + { + if (str[i] == '-') + sign = -1; + if (str[i] == '+') + sign = 1; + i++; + } + out = 0; + while (str[i] >= '0' && str[i] <= '9') + { + out = out * 10 + str[i] - 48; + i++; + } + return (out * sign); +} diff --git a/utils/ft_isnum.c b/utils/ft_isnum.c new file mode 100644 index 0000000..f78e9ad --- /dev/null +++ b/utils/ft_isnum.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isnum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cchauvet '9' || str[i] < '0') + return (0); + i++; + } + return (1); +} diff --git a/utils/utils.h b/utils/utils.h new file mode 100644 index 0000000..28d5e05 --- /dev/null +++ b/utils/utils.h @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cchauvet +# include + +bool ft_isnum(char str[]); +int ft_atoi(const char str[]); + +#endif