diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2020-09-29 14:56:27 +0200 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2020-09-29 14:56:27 +0200 |
| commit | 6bfcd3c6f921e7717e61167b291bb27bd3f66386 (patch) | |
| tree | 67b2aa4b8a036cb355f90b1f94438b7eb46441f1 /philo_one/src | |
| parent | ac4278405b7a258010219499cccc0dd978201caf (diff) | |
| download | philosophers-6bfcd3c6f921e7717e61167b291bb27bd3f66386.tar.gz philosophers-6bfcd3c6f921e7717e61167b291bb27bd3f66386.tar.bz2 philosophers-6bfcd3c6f921e7717e61167b291bb27bd3f66386.zip | |
Fixing taking none existing fork in logs
Diffstat (limited to 'philo_one/src')
| -rw-r--r-- | philo_one/src/args.c | 32 | ||||
| -rw-r--r-- | philo_one/src/forks.c | 60 | ||||
| -rw-r--r-- | philo_one/src/helper.c | 99 | ||||
| -rw-r--r-- | philo_one/src/io.c | 81 | ||||
| -rw-r--r-- | philo_one/src/main.c | 48 | ||||
| -rw-r--r-- | philo_one/src/philo.c | 61 | ||||
| -rw-r--r-- | philo_one/src/philo_one.h | 123 | ||||
| -rw-r--r-- | philo_one/src/routine.c | 56 |
8 files changed, 560 insertions, 0 deletions
diff --git a/philo_one/src/args.c b/philo_one/src/args.c new file mode 100644 index 0000000..b7277dd --- /dev/null +++ b/philo_one/src/args.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* args.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/08 23:12:55 by cacharle #+# #+# */ +/* Updated: 2020/09/29 11:08:06 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +bool parse_args(t_philo_conf *philo_args, int argc, char **argv) +{ + if (argc != 5 && argc != 6) + return h_err(false, "Usage: %s philosophers_num death_timeout eat_timeout sleep_timeout [meal_num]", argv[0]); + if ((philo_args->philo_num = h_atou_strict(argv[1])) == -1 + || (philo_args->timeout_death = h_atou_strict(argv[2])) == -1 + || (philo_args->timeout_eat = h_atou_strict(argv[3])) == -1 + || (philo_args->timeout_sleep = h_atou_strict(argv[4])) == -1) + return (false); + if (argc == 6) + { + if ((philo_args->meal_num = h_atou_strict(argv[5])) == -1) + return (false); + } + else + philo_args->meal_num = 1; + return (true); +} diff --git a/philo_one/src/forks.c b/philo_one/src/forks.c new file mode 100644 index 0000000..ebe5261 --- /dev/null +++ b/philo_one/src/forks.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* forks.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/09 23:46:40 by cacharle #+# #+# */ +/* Updated: 2020/09/27 09:26:12 by charles ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +pthread_mutex_t *forks_new(int num) +{ + int i; + pthread_mutex_t *forks; + + if ((forks = malloc(num * sizeof(pthread_mutex_t))) == NULL) + return (NULL); + i = -1; + while (++i < num) + { + if (pthread_mutex_init(&forks[i], NULL) != 0) + { + forks_destroy(forks, i + 1); + return (NULL); + } + } + return (forks); +} + +void forks_destroy(pthread_mutex_t *forks, int num) +{ + while (num-- > 0) + pthread_mutex_destroy(&forks[num]); + free(forks); +} + +t_routine_arg *forks_dispatch( + t_philo *philos, + pthread_mutex_t *forks, + t_philo_conf *conf) +{ + int i; + t_routine_arg *routine_args; + + if ((routine_args = malloc(conf->philo_num * sizeof(t_routine_arg))) == NULL) + return (NULL); + i = -1; + while (++i < conf->philo_num) + { + routine_args[i].conf = conf; + routine_args[i].philo = philos + i; + routine_args[i].fork_left = forks + i % conf->philo_num; + routine_args[i].fork_right = forks + (i + 1) % conf->philo_num; + } + return (routine_args); +} diff --git a/philo_one/src/helper.c b/philo_one/src/helper.c new file mode 100644 index 0000000..fa4c7ff --- /dev/null +++ b/philo_one/src/helper.c @@ -0,0 +1,99 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* helper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/08 23:22:49 by cacharle #+# #+# */ +/* Updated: 2020/09/29 14:15:50 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +static int h_strlen(char *s) +{ + int counter; + + counter = 0; + while (s[counter]) + counter++; + return (counter); +} + +long int h_atou_strict(char *s) +{ + long int num; + char *origin; + + origin = s; + if (*s < '0' || *s > '9') + return (h_err(-1, "Error: %s: is not a number", origin)); + num = 0; + while (*s >= '0' && *s <= '9') + { + num *= 10; + if (num > UINT_MAX) + return (h_err(-1, "Error: %s: is too big", origin)); + num += *s - '0'; + if (num > UINT_MAX) + return (h_err(-1, "Error: %s: is too big", origin)); + s++; + } + if (*s != '\0') + return (h_err(-1, "Error: %s: is not a number", origin)); + return (num); +} + +void h_putnbr(unsigned long int num) +{ + if (num > 9) + h_putnbr(num / 10); + h_putchar(num % 10 + '0'); +} + +void h_putchar(char c) +{ + write(STDOUT_FILENO, &c, 1); +} + +void h_putstr(char *s) +{ + write(STDOUT_FILENO, s, h_strlen(s)); +} + +int h_err(int ret, const char *format, ...) +{ + char *str; + va_list ap; + + va_start(ap, format); + while (*format != '\0') + { + if (format[0] == '%' && format[1] == 's') + { + str = va_arg(ap, char*); + if (str != NULL) + write(STDERR_FILENO, str, h_strlen(str)); + format += 2; + } + else + { + write(STDERR_FILENO, format, 1); + format++; + } + } + va_end(ap); + write(STDERR_FILENO, "\n", 1); + return (ret); +} + +t_time h_time_now(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL) == -1) + return (-1); + return (tv.tv_sec * 1000 + tv.tv_usec / 1000); +} diff --git a/philo_one/src/io.c b/philo_one/src/io.c new file mode 100644 index 0000000..96a8f07 --- /dev/null +++ b/philo_one/src/io.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* io.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/14 21:37:50 by cacharle #+# #+# */ +/* Updated: 2020/09/29 14:55:21 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +static void philo_put(int id, t_philo_event event) +{ + h_putnbr(h_time_now()); + h_putchar(' '); + h_putnbr(id); + if (event == EVENT_FORK) + h_putstr(" has taken fork\n"); + else if (event == EVENT_EAT) + h_putstr(" is eating\n"); + else if (event == EVENT_SLEEP) + h_putstr(" is sleeping\n"); + else if (event == EVENT_THINK) + h_putstr(" is thinking\n"); + else if (event == EVENT_DIE) + h_putstr(" died\n"); +} + +void io_eat(t_routine_arg *arg) +{ + int eat_counter; + + eat_counter = 0; + while (eat_counter < arg->conf->meal_num) + { + pthread_mutex_lock(&arg->conf->mutex_all_alive); + if (!arg->conf->all_alive) + return ; + pthread_mutex_lock(&arg->conf->mutex_stdout); + philo_put(arg->philo->id, EVENT_EAT); + pthread_mutex_unlock(&arg->conf->mutex_stdout); + pthread_mutex_unlock(&arg->conf->mutex_all_alive); + usleep(arg->conf->timeout_eat * 1000); + eat_counter++; + } +} + +void io_think(t_routine_arg *arg) +{ + pthread_mutex_lock(&arg->conf->mutex_all_alive); + if (!arg->conf->all_alive) + return ; + pthread_mutex_lock(&arg->conf->mutex_stdout); + philo_put(arg->philo->id, EVENT_THINK); + pthread_mutex_unlock(&arg->conf->mutex_stdout); + pthread_mutex_unlock(&arg->conf->mutex_all_alive); +} + +void io_sleep(t_routine_arg *arg) +{ + pthread_mutex_lock(&arg->conf->mutex_all_alive); + if (!arg->conf->all_alive) + return ; + pthread_mutex_lock(&arg->conf->mutex_stdout); + philo_put(arg->philo->id, EVENT_SLEEP); + pthread_mutex_unlock(&arg->conf->mutex_stdout); + pthread_mutex_unlock(&arg->conf->mutex_all_alive); + /* usleep(arg->conf->timeout_sleep * 1000); */ +} + +void io_die(t_routine_arg *arg) +{ + if (!arg->conf->all_alive) + return ; + pthread_mutex_lock(&arg->conf->mutex_stdout); + philo_put(arg->philo->id, EVENT_DIE); + pthread_mutex_unlock(&arg->conf->mutex_stdout); +} diff --git a/philo_one/src/main.c b/philo_one/src/main.c new file mode 100644 index 0000000..511fdbe --- /dev/null +++ b/philo_one/src/main.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2019/11/24 05:53:02 by cacharle #+# #+# */ +/* Updated: 2020/09/29 13:26:07 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +int main(int argc, char **argv) +{ + t_philo_conf philo_args; + t_philo *philos; + pthread_mutex_t *forks; + t_routine_arg *routine_args; + + if (!parse_args(&philo_args, argc, argv)) + return (1); + if (philo_args.philo_num == 0) + return (0); + if ((forks = forks_new(philo_args.philo_num)) == NULL) + return (1); + if ((philos = philos_new(philo_args.philo_num)) == NULL) + return (1); + if ((routine_args = forks_dispatch(philos, forks, &philo_args)) == NULL) + return (1); + philo_args.all_alive = true; + pthread_mutex_init(&philo_args.mutex_all_alive, NULL); + pthread_mutex_init(&philo_args.mutex_stdout, NULL); + if (!philos_start(philos, routine_args, philo_args.philo_num)) + return (1); + /* pthread_mutex_lock(philo_args.mutex_all_alive); */ + /* pthread_mutex_lock(philo_args.mutex_all_alive); */ + while (philo_args.all_alive) + ; + philos_join(philos, philo_args.philo_num); + pthread_mutex_destroy(&philo_args.mutex_stdout); + pthread_mutex_destroy(&philo_args.mutex_all_alive); + free(routine_args); + free(philos); + forks_destroy(forks, philo_args.philo_num); + return (0); +} diff --git a/philo_one/src/philo.c b/philo_one/src/philo.c new file mode 100644 index 0000000..e0ecfec --- /dev/null +++ b/philo_one/src/philo.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/09 23:47:14 by cacharle #+# #+# */ +/* Updated: 2020/09/29 13:29:49 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +t_philo *philos_new(int num) +{ + int i; + t_philo *philos; + + if (num < 0) + return (NULL); + if ((philos = malloc(num * sizeof(t_philo))) == NULL) + return (NULL); + i = -1; + while (++i < num) + { + philos[i].id = i + 1; + philos[i].alive = false; + } + return (philos); +} + +bool philos_start(t_philo *philos, t_routine_arg *routine_args, int num) +{ + int i; + + i = -1; + while (++i < num) + { + philos[i].alive = true; + if (pthread_create(&philos[i].thread, NULL, + (void *(*)(void*))routine_philo, (void*)(routine_args + i)) == -1) + return (false); + } + return (true); +} + +void philos_join(t_philo *philos, int num) +{ + int i; + + i = -1; + while (++i < num) + { + if (philos[i].alive) + { + philos[i].alive = false; + pthread_detach(philos[i].thread); + } + } +} diff --git a/philo_one/src/philo_one.h b/philo_one/src/philo_one.h new file mode 100644 index 0000000..e92fdcd --- /dev/null +++ b/philo_one/src/philo_one.h @@ -0,0 +1,123 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* philo_one.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2019/11/24 06:11:16 by cacharle #+# #+# */ +/* Updated: 2020/09/29 14:15:47 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PHILO_ONE_H +# define PHILO_ONE_H + +# include <unistd.h> +# include <sys/time.h> +# include <stdlib.h> +# include <pthread.h> +# include <stdbool.h> +# include <limits.h> +# include <stdarg.h> + +typedef long int t_time; + +typedef enum +{ + EVENT_FORK, + EVENT_EAT, + EVENT_SLEEP, + EVENT_THINK, + EVENT_DIE +} t_philo_event; + +typedef struct +{ + int philo_num; + t_time timeout_death; + t_time timeout_eat; + t_time timeout_sleep; + int meal_num; + bool all_alive; + pthread_mutex_t mutex_stdout; + pthread_mutex_t mutex_all_alive; +} t_philo_conf; + +typedef struct s_philo +{ + int id; + bool alive; + t_time time_last_eat; + pthread_t thread; +} t_philo; + +typedef struct s_routine_arg +{ + t_philo_conf *conf; + t_philo *philo; + pthread_mutex_t *fork_left; + pthread_mutex_t *fork_right; + pthread_mutex_t *mutex_stdout; +} t_routine_arg; + +/* +** forks.c +*/ + +pthread_mutex_t *forks_new(int num); +void forks_destroy(pthread_mutex_t *forks, int num); +t_routine_arg *forks_dispatch( + t_philo *philos, + pthread_mutex_t *forks, + t_philo_conf *conf); + +/* +** philo.c +*/ + +t_philo *philos_new(int num); +void philos_destroy(t_philo *philos, int num); +bool philos_start( + t_philo *philos, + t_routine_arg *routine_args, + int num); +void philos_join(t_philo *philos, int num); + +/* +** routine.c +*/ + +void *routine_philo(t_routine_arg *arg); +void *routine_death(t_routine_arg *arg); + +/* +** io.c +*/ + +void io_eat(t_routine_arg *arg); +void io_think(t_routine_arg *arg); +void io_sleep(t_routine_arg *arg); +void io_die(t_routine_arg *arg); + +/* +** common.c +*/ + +bool parse_args( + t_philo_conf *philo_args, + int argc, + char **argv); + +/* +** helper.c +*/ + +long int h_atou_strict(char *s); +void h_putnbr(unsigned long num); +void h_putchar(char c); +void h_putstr(char *s); +int h_err(int ret, const char *format, ...); +t_time h_time_now(void); + +#endif diff --git a/philo_one/src/routine.c b/philo_one/src/routine.c new file mode 100644 index 0000000..0115e91 --- /dev/null +++ b/philo_one/src/routine.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* routine.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/10 01:11:27 by cacharle #+# #+# */ +/* Updated: 2020/09/29 14:30:06 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "philo_one.h" + +void *routine_philo(t_routine_arg *arg) +{ + pthread_t thread_death; + + if (!arg->conf->all_alive) + return (NULL); + arg->philo->time_last_eat = h_time_now(); + if (pthread_create(&thread_death, NULL, (void *(*)(void*))routine_death, arg) != 0) + return (NULL); + io_think(arg); + while (arg->conf->all_alive) + { + pthread_mutex_lock(arg->fork_left); + pthread_mutex_lock(arg->fork_right); + arg->philo->time_last_eat = h_time_now(); + io_eat(arg); + io_sleep(arg); + pthread_mutex_unlock(arg->fork_right); + pthread_mutex_unlock(arg->fork_left); + usleep(arg->conf->timeout_sleep * 1000); + io_think(arg); + } + pthread_join(thread_death, NULL); + return (NULL); +} + +void *routine_death(t_routine_arg *arg) +{ + t_time current; + + current = h_time_now(); + while (arg->conf->all_alive && + current - arg->philo->time_last_eat < arg->conf->timeout_death) + current = h_time_now(); + if (!arg->conf->all_alive) + return (NULL); + pthread_mutex_lock(&arg->conf->mutex_all_alive); + io_die(arg); + arg->conf->all_alive = false; + pthread_mutex_unlock(&arg->conf->mutex_all_alive); + return (NULL); +} |
