aboutsummaryrefslogtreecommitdiff
path: root/philo_one/src
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-09-29 14:56:27 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-09-29 14:56:27 +0200
commit6bfcd3c6f921e7717e61167b291bb27bd3f66386 (patch)
tree67b2aa4b8a036cb355f90b1f94438b7eb46441f1 /philo_one/src
parentac4278405b7a258010219499cccc0dd978201caf (diff)
downloadphilosophers-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.c32
-rw-r--r--philo_one/src/forks.c60
-rw-r--r--philo_one/src/helper.c99
-rw-r--r--philo_one/src/io.c81
-rw-r--r--philo_one/src/main.c48
-rw-r--r--philo_one/src/philo.c61
-rw-r--r--philo_one/src/philo_one.h123
-rw-r--r--philo_one/src/routine.c56
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);
+}