Implement the hunger watcher, rename function
authorLukas Jiriste <ljiriste@student.42prague.com>
Fri, 24 May 2024 08:13:27 +0000 (10:13 +0200)
committerLukas Jiriste <ljiriste@student.42prague.com>
Fri, 24 May 2024 08:34:45 +0000 (10:34 +0200)
The hunger watcher watches for starvation in calling philo
making him die when he starves (is hungry for too long).
The function print_timestamp is split to make it possible to
ensure the "philo died" message is the last one.

philo_bonus/Makefile
philo_bonus/helpers.c
philo_bonus/hunger_watcher.c [new file with mode: 0644]
philo_bonus/philo.c
philo_bonus/philo.h

index 0044792a478e5cb65246d3b639166daaa06e0629..67db9ebc70ed5eac25714bab687433c24ea9af68 100644 (file)
@@ -14,6 +14,7 @@ SRCS :=       main.c                          \
                pars_arg.c                      \
                inner_pars_arg.c        \
                mem_management.c        \
+               hunger_watcher.c        \
 
 SRCS := $(addprefix $(SRCDIR)/, $(SRCS))
 OBJS := $(SRCS:%.c=%.o)
index 20dfa3058d09f31d00fa29a4030c9f095ceebbef..bfed896b128a791ad06d9014a2ade9bc8b57bfa8 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/05/09 09:13:40 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/05/24 09:21:50 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/05/24 10:26:10 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -34,12 +34,18 @@ int is_alive(t_philo *philo)
 }
 
 void   print_timestamp(t_philo *philo, const char *str)
+{
+       printf("%u %u %s\n", usecs_since_start(philo->settings.start)
+               / 1000, philo->id, str);
+       return ;
+}
+
+void   report(t_philo *philo, const char *str)
 {
        if (is_alive(philo))
        {
                sem_wait(philo->semaphores[term]);
-               printf("%u %u %s\n", usecs_since_start(philo->settings.start)
-                       / 1000, philo->id, str);
+               print_timestamp(philo, str);
                sem_post(philo->semaphores[term]);
        }
        return ;
diff --git a/philo_bonus/hunger_watcher.c b/philo_bonus/hunger_watcher.c
new file mode 100644 (file)
index 0000000..b22b59b
--- /dev/null
@@ -0,0 +1,61 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   hunger_watcher.c                                   :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2024/05/24 08:49:46 by ljiriste          #+#    #+#             */
+/*   Updated: 2024/05/24 10:33:27 by ljiriste         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <pthread.h>
+
+//     This function should only be called when the philo_sem is locked
+//     by this thread.
+static useconds_t      time_till_death(t_philo *philo)
+{
+       const useconds_t        cur_time = usecs_since_start(philo->settings.start);
+
+       if (cur_time >= philo->last_eaten + philo->settings.time_to_die)
+               return (0);
+       return (philo->last_eaten + philo->settings.time_to_die - cur_time);
+}
+
+//     The lock of philo_sem is done this way because philo has to be lock
+//     between the time calculation and setting him as not alive.
+//     Else the philo could eat in between the watcher deciding to kill him
+//     and executing it.
+static void    *watch_for_starvation(void *philo_void)
+{
+       t_philo         *philo;
+       useconds_t      time;
+
+       philo = philo_void;
+       sem_wait(philo->philo_sem);
+       time = time_till_death(philo);
+       while (time == 0)
+       {
+               sem_post(philo->philo_sem);
+               usleep(time / 2);
+               sem_wait(philo->philo_sem);
+               time = time_till_death(philo);
+       }
+       philo->alive = 0;
+       sem_post(philo->semaphores[death]);
+       sem_post(philo->philo_sem);
+       return (NULL);
+}
+
+int    create_hunger_watcher(t_philo *philo, pthread_t *hunger_watcher)
+{
+       return (pthread_create(hunger_watcher, NULL, watch_for_starvation, philo));
+}
+
+void   destroy_hunger_watcher(pthread_t hunger_watcher)
+{
+       pthread_join(hunger_watcher, NULL);
+       return ;
+}
index 6c499208917cb921053b26f825a3e6b27c002a59..b9ce802c1b6d7d5ff5c8f7c64c57ee6c4dfb94ff 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/05/09 08:45:21 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/05/24 08:44:24 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/05/24 10:32:38 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -16,7 +16,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-static void    open_semaphores(t_philo *philo)
+static int     open_semaphores(t_philo *philo)
 {
        char    *sem_name;
 
@@ -32,28 +32,28 @@ static void open_semaphores(t_philo *philo)
                sem_wait(philo->semaphores[term]);
                printf("An error has occured.\n");
                sem_wait(philo->semaphores[death]);
-               exit(2);
+               return (1);
        }
-       return ;
+       return (0);
 }
 
 static void    philo_think(t_philo *philo)
 {
-       print_timestamp(philo, "is thinking");
+       report(philo, "is thinking");
        return ;
 }
 
 static void    philo_eat(t_philo *philo)
 {
        sem_wait(philo->semaphores[forks]);
-       print_timestamp(philo, "has taken a fork");
+       report(philo, "has taken a fork");
        sem_wait(philo->semaphores[forks]);
-       print_timestamp(philo, "has taken a fork");
+       report(philo, "has taken a fork");
        sem_wait(philo->philo_sem);
        philo->last_eaten = usecs_since_start(philo->settings.start);
        ++philo->num_eaten;
        sem_post(philo->philo_sem);
-       print_timestamp(philo, "is eating");
+       report(philo, "is eating");
        if (philo->settings.should_check_hunger &&
                philo->num_eaten == philo->settings.min_eat_num)
                sem_post(philo->semaphores[fed]);
@@ -65,23 +65,25 @@ static void philo_eat(t_philo *philo)
 
 static void    philo_sleep(t_philo *philo)
 {
-       print_timestamp(philo, "is sleeping");
+       report(philo, "is sleeping");
        usleep(philo->settings.time_to_sleep);
        return ;
 }
 
 void   be_a_philosopher(t_philo *philo)
 {
-       pid_t   hunger_watcher_pid;
+       pthread_t       hunger_watcher;
 
-       open_semaphores(philo);
-       hunger_watcher_pid = create_hunger_watcher(philo);
+       if (open_semaphores(philo))
+               exit(2);
+       if (create_hunger_watcher(philo, &hunger_watcher))
+               exit(3);
        while (is_alive(philo))
        {
                philo_think(philo);
                philo_eat(philo);
                philo_sleep(philo);
        }
-       destroy_hunger_watcher(hunger_watcher_pid);
+       destroy_hunger_watcher(hunger_watcher);
        exit(0);
 }
index 625c60fa73b715e5638797c7c1d889839afffc9d..65af18edfa166c786790ad76c2baa328ba735aea 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/03/22 11:10:17 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/05/24 09:21:24 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/05/24 10:32:59 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -72,10 +72,13 @@ int                 init(unsigned int count, pid_t **philo_pids,
 void           cleanup(pid_t *philo_pids, sem_t *semaphores[sem_num]);
 
 useconds_t     usecs_since_start(struct timeval start);
-int                    report(t_philo *philo, const char *str);
 int                    is_alive(t_philo *philo);
+void           report(t_philo *philo, const char *str);
 void           print_timestamp(t_philo *philo, const char *str);
 
+int                    create_hunger_watcher(t_philo *philo, pthread_t *hunger_watcher);
+void           destroy_hunger_watcher(pthread_t hunger_watcher);
+
 void           be_a_philosopher(t_philo *philo);
 
 #endif //PHILO_H