HEADERS = -Iinclude
VPATH := src
-SRC := main.c ft_utils.c simulation.c
+SRC := main.c ft_utils.c simulation.c philo_eat.c
OBJ_DIR := _obj
OBJ := $(addprefix $(OBJ_DIR)/, $(SRC:%.c=%.o))
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/17 11:57:44 by dkaiser #+# #+# */
-/* Updated: 2025/01/18 13:04:16 by dkaiser ### ########.fr */
+/* Updated: 2025/01/21 12:04:07 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef FT_UTILS_H
# define FT_UTILS_H
-# include <stdlib.h>
# include <stdio.h>
+# include <stdlib.h>
# include <sys/time.h>
/*
** Prints error message and returns EXIT_FAILURE
*/
-int ft_err(const char *str);
+int ft_err(const char *str);
/*
** Returns integer value from str
*/
-int ft_atoi(const char *str);
+int ft_atoi(const char *str);
/*
** Returns current time in milliseconds
*/
-int ft_cur_time_in_ms();
+int ft_cur_time_in_ms(void);
/*
** Prints "timestamp_in_ms id str"
*/
-void ft_log(int id, const char *str);
+void ft_log(int id, const char *str);
#endif
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/17 10:23:19 by dkaiser #+# #+# */
-/* Updated: 2025/01/18 17:09:50 by dkaiser ### ########.fr */
+/* Updated: 2025/01/26 12:05:33 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PHILO_H
# define PHILO_H
-# include <unistd.h>
-# include <stdlib.h>
-# include <stdio.h>
-# include <pthread.h>
# include "ft_utils.h"
+# include <pthread.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
# define ERR_USAGE "Usage: <nbr_of_philos> <ttd> <tte> <tts> [times_must_eat]"
# define ERR_MALLOC "Memory allocation failed"
typedef struct s_fork
{
- int available;
- pthread_mutex_t mutex;
-} t_fork;
+ int owner;
+ pthread_mutex_t mutex;
+} t_fork;
typedef struct s_phdata
{
- int nbr_of_philos;
- int time_to_die;
- int time_to_eat;
- int time_to_sleep;
- int times_must_eat;
- int philos_must_eat;
- pthread_mutex_t pme_mutex;
- int simulation_running;
- t_fork *forks;
-} t_phdata;
+ int nbr_of_philos;
+ int time_to_die;
+ int time_to_eat;
+ int time_to_sleep;
+ int times_must_eat;
+ int philos_must_eat;
+ pthread_mutex_t pme_mutex;
+ int simulation_running;
+ t_fork *forks;
+} t_phdata;
typedef struct s_philo
{
- int id;
- int last_time_eaten;
- int times_must_eat;
- int is_alive;
- pthread_t thread;
- t_phdata *data;
-} t_philo;
-
-int run_simulation(int nbr_of_philos, t_philo *philos, t_phdata *data);
+ int id;
+ int last_time_eaten;
+ int times_must_eat;
+ int is_alive;
+ pthread_t thread;
+ t_phdata *data;
+} t_philo;
+
+int run_simulation(int nbr_of_philos, t_philo *philos,
+ t_phdata *data);
+int philo_die(t_philo *philo);
+void philo_eat(t_philo *philo);
#endif
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/17 11:57:11 by dkaiser #+# #+# */
-/* Updated: 2025/01/18 13:04:08 by dkaiser ### ########.fr */
+/* Updated: 2025/01/21 12:04:22 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "ft_utils.h"
-int ft_err(const char *str)
+int ft_err(const char *str)
{
- printf("\e[31m[ERROR] %s\e[0m\n", str);
- return (EXIT_FAILURE);
+ printf("\e[31m[ERROR] %s\e[0m\n", str);
+ return (EXIT_FAILURE);
}
-int ft_cur_time_in_ms()
+int ft_cur_time_in_ms(void)
{
- int time_in_ms;
- struct timeval t;
+ int time_in_ms;
+ struct timeval t;
gettimeofday(&t, NULL);
time_in_ms = (t.tv_sec * 1000) + (t.tv_usec / 1000);
return (time_in_ms);
}
-void ft_log(int id, const char *str)
+void ft_log(int id, const char *str)
{
printf("%u %d %s\n", ft_cur_time_in_ms(), id, str);
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/14 17:13:30 by dkaiser #+# #+# */
-/* Updated: 2025/01/18 17:09:26 by dkaiser ### ########.fr */
+/* Updated: 2025/01/26 12:05:55 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
+int load_data(t_phdata *data, int argc, char *argv[])
+{
+ data->nbr_of_philos = ft_atoi(argv[1]);
+ data->time_to_die = ft_atoi(argv[2]);
+ data->time_to_eat = ft_atoi(argv[3]);
+ data->time_to_sleep = ft_atoi(argv[4]);
+ if (argc == 6)
+ data->times_must_eat = ft_atoi(argv[5]);
+ else
+ data->times_must_eat = -1;
+ if (data->nbr_of_philos <= 0)
+ return (ft_err("Must have at least one philosopher"));
+ if (data->time_to_die < 0)
+ return (ft_err("ttd can't be negative"));
+ if (data->time_to_eat < 0)
+ return (ft_err("tte can't be negative"));
+ if (data->time_to_sleep < 0)
+ return (ft_err("tts can't be negative"));
+ data->philos_must_eat = data->nbr_of_philos;
+ return (EXIT_SUCCESS);
+}
+
+void init_philo(t_philo *philo, t_phdata *data, int id)
+{
+ philo->id = id;
+ philo->is_alive = 1;
+ philo->times_must_eat = data->times_must_eat;
+ philo->data = data;
+ philo->last_time_eaten = ft_cur_time_in_ms();
+}
-int load_data(t_phdata *data, int argc, char *argv[])
+int init_philos(t_philo **philos, t_phdata *data)
{
- data->nbr_of_philos = ft_atoi(argv[1]);
- data->time_to_die = ft_atoi(argv[2]);
- data->time_to_eat = ft_atoi(argv[3]);
- data->time_to_sleep = ft_atoi(argv[4]);
- if (argc == 6)
- data->times_must_eat = ft_atoi(argv[5]);
- else
- data->times_must_eat = -1;
- if (data->nbr_of_philos <= 0)
- return (ft_err("Must have at least one philosopher"));
- if (data->time_to_die < 0)
- return (ft_err("ttd can't be negative"));
- if (data->time_to_eat < 0)
- return (ft_err("tte can't be negative"));
- if (data->time_to_sleep < 0)
- return (ft_err("tts can't be negative"));
- data->philos_must_eat = data->nbr_of_philos;
- return (EXIT_SUCCESS);
+ int i;
+ int result;
+
+ i = 0;
+ while (i < data->nbr_of_philos)
+ {
+ init_philo(&(*philos)[i], data, i + 1);
+ data->forks[i].owner = 0;
+ result = pthread_mutex_init(&(data->forks[i].mutex), NULL);
+ if (result != 0)
+ {
+ free(*philos);
+ free(data->forks);
+ return (result);
+ }
+ i++;
+ }
+ return (EXIT_SUCCESS);
}
-int init(t_philo **philos, t_phdata *data)
+int init(t_philo **philos, t_phdata *data)
{
- int i;
- int result;
+ int result;
- *philos = (t_philo *)malloc(sizeof(t_philo) * data->nbr_of_philos);
- if (*philos == NULL)
- return (ft_err(ERR_MALLOC));
- data->forks = (t_fork *)malloc(sizeof(t_fork) * data->nbr_of_philos);
- if (data->forks == NULL)
- {
- free(*philos);
- return (ft_err(ERR_MALLOC));
- }
- i = 0;
- result = pthread_mutex_init(&(data->forks[i].mutex), NULL);
- if (result != 0)
- {
- free(*philos);
- free(data->forks);
- return (result);
- }
- while (i < data->nbr_of_philos)
- {
- (*philos)[i].id = i + 1;
- (*philos)[i].is_alive = 1;
- (*philos)[i].times_must_eat = data->times_must_eat;
- (*philos)[i].data = data;
- (*philos)[i].last_time_eaten = ft_cur_time_in_ms();
- data->forks[i].available = 1;
- result = pthread_mutex_init(&(data->forks[i].mutex), NULL);
- if (result != 0)
- {
- free(*philos);
- free(data->forks);
- return (result);
- }
- i++;
- }
- return (EXIT_SUCCESS);
+ *philos = (t_philo *)malloc(sizeof(t_philo) * data->nbr_of_philos);
+ if (*philos == NULL)
+ return (ft_err(ERR_MALLOC));
+ data->forks = (t_fork *)malloc(sizeof(t_fork) * data->nbr_of_philos);
+ if (data->forks == NULL)
+ {
+ free(*philos);
+ return (ft_err(ERR_MALLOC));
+ }
+ result = pthread_mutex_init(&(data->pme_mutex), NULL);
+ if (result != 0)
+ {
+ free(*philos);
+ free(data->forks);
+ return (result);
+ }
+ result = init_philos(philos, data);
+ return (result);
}
-int main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
- t_phdata data;
- t_philo *philos;
- int result;
+ t_phdata data;
+ t_philo *philos;
+ int result;
- if (argc != 5 && argc != 6)
- return(ft_err(ERR_USAGE));
- result = load_data(&data, argc, argv);
- if (result != EXIT_SUCCESS)
- return (result);
- result = init(&philos, &data);
- if (result != EXIT_SUCCESS)
- return (result);
- data.simulation_running = 1;
- result = run_simulation(data.nbr_of_philos, philos, &data);
- free(philos);
- free(data.forks);
- return (result);
+ if (argc != 5 && argc != 6)
+ return (ft_err(ERR_USAGE));
+ result = load_data(&data, argc, argv);
+ if (result != EXIT_SUCCESS)
+ return (result);
+ result = init(&philos, &data);
+ if (result != EXIT_SUCCESS)
+ return (result);
+ data.simulation_running = 1;
+ result = run_simulation(data.nbr_of_philos, philos, &data);
+ free(philos);
+ free(data.forks);
+ return (result);
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/17 14:38:04 by dkaiser #+# #+# */
-/* Updated: 2025/01/18 17:09:34 by dkaiser ### ########.fr */
+/* Updated: 2025/01/26 12:43:53 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
-int philo_die(t_philo *philo)
+int philo_die(t_philo *philo)
{
- if (ft_cur_time_in_ms() > philo->last_time_eaten + philo->data->time_to_die)
- {
- philo->is_alive = 0;
- ft_log(philo->id, "has died");
- philo->data->simulation_running = 0;
- return (1);
- }
- return (0);
+ if (ft_cur_time_in_ms() > philo->last_time_eaten + philo->data->time_to_die)
+ {
+ philo->is_alive = 0;
+ ft_log(philo->id, "has died");
+ philo->data->simulation_running = 0;
+ return (1);
+ }
+ return (0);
}
-void philo_eat(t_philo *philo)
+void philo_sleep(t_philo *philo)
{
- t_fork *left_fork;
- t_fork *right_fork;
- int started_eating;
- int tte;
+ int started_sleeping;
+ int tts;
- left_fork = &philo->data->forks[philo->id - 1];
- right_fork = &philo->data->forks[philo->id % philo->data->nbr_of_philos];
- while (!left_fork->available || !right_fork->available)
- {
- if (!philo->data->simulation_running)
- return;
- if (philo_die(philo))
- return ;
- usleep(1000);
- }
- pthread_mutex_lock(&left_fork->mutex);
- pthread_mutex_lock(&right_fork->mutex);
- if (philo->data->simulation_running)
- {
-
- left_fork->available = 0;
- ft_log(philo->id, "has taken a fork");
- right_fork->available = 0;
- ft_log(philo->id, "has taken a fork");
- started_eating = ft_cur_time_in_ms();
- tte = philo->data->time_to_eat;
- philo->last_time_eaten = started_eating;
- philo->times_must_eat -= 1;
- ft_log(philo->id, "is eating");
- while (ft_cur_time_in_ms() < started_eating + tte)
- {
- if (philo_die(philo))
- return;
- usleep(1000);
- }
- left_fork->available = 1;
- right_fork->available = 1;
- }
- pthread_mutex_unlock(&left_fork->mutex);
- pthread_mutex_unlock(&right_fork->mutex);
-}
-
-void philo_sleep(t_philo *philo)
-{
- int started_sleeping;
- int tts;
-
- started_sleeping = ft_cur_time_in_ms();
- tts = philo->data->time_to_sleep;
- ft_log(philo->id, "is sleeping");
- while (ft_cur_time_in_ms() < started_sleeping + tts)
- {
- if (philo_die(philo))
- return;
- usleep(1000);
- }
-}
-
-void philo_think(t_philo *philo)
-{
- ft_log(philo->id, "is thinking");
+ started_sleeping = ft_cur_time_in_ms();
+ tts = philo->data->time_to_sleep;
+ ft_log(philo->id, "is sleeping");
+ while (ft_cur_time_in_ms() < started_sleeping + tts)
+ {
+ if (philo_die(philo))
+ return ;
+ usleep(1000);
+ }
}
-int *process_philo(void *arg)
+void process_philo(void *arg)
{
- t_philo *philo;
- int *result;
+ t_philo *philo;
- result = malloc(sizeof(int));
- if (result == NULL)
- return (NULL);
- philo = (t_philo *)arg;
- *result = EXIT_SUCCESS;
- while (philo->data->simulation_running)
- {
- philo_eat(philo);
- if (philo->times_must_eat == 0)
- {
- pthread_mutex_lock(&philo->data->pme_mutex);
- philo->data->philos_must_eat -= 1;
- pthread_mutex_unlock(&philo->data->pme_mutex);
- }
- if (!philo->data->simulation_running)
- break;
- philo_sleep(philo);
- if (!philo->data->simulation_running)
- break;
- philo_think(philo);
- }
- return (result);
+ philo = (t_philo *)arg;
+ while (philo->data->simulation_running)
+ {
+ philo_eat(philo);
+ if (philo->times_must_eat == 0)
+ {
+ pthread_mutex_lock(&philo->data->pme_mutex);
+ philo->data->philos_must_eat -= 1;
+ pthread_mutex_unlock(&philo->data->pme_mutex);
+ }
+ if (!philo->data->simulation_running)
+ break ;
+ if (philo->data->nbr_of_philos < 2)
+ {
+ if (philo_die(philo))
+ break ;
+ continue ;
+ }
+ philo_sleep(philo);
+ if (!philo->data->simulation_running)
+ break ;
+ ft_log(philo->id, "is thinking");
+ }
}
-int run_simulation(int nbr_of_philos, t_philo *philos, t_phdata *data)
+int run_simulation(int nbr_of_philos, t_philo *philos, t_phdata *data)
{
- int i;
- int result;
- void *retval;
+ int i;
+ int result;
- i = 0;
- result = EXIT_SUCCESS;
- while (i < nbr_of_philos)
- {
- result = pthread_create(&(philos[i].thread), NULL, (void*) process_philo, &philos[i]);
- if (result != 0)
- break;
- i++;
- }
- while (data->simulation_running)
- {
- if (data->philos_must_eat <= 0)
- data->simulation_running = 0;
- }
- while (i--)
- {
- pthread_join(philos[i].thread, &retval);
- if (retval == NULL)
- result = ft_err(ERR_MALLOC);
- else if (*(int *)retval != EXIT_SUCCESS)
- {
- result = *(int *)retval;
- free(retval);
- }
- }
- return (result);
+ i = 0;
+ result = EXIT_SUCCESS;
+ while (i < nbr_of_philos)
+ {
+ result = pthread_create(&(philos[i].thread), NULL,
+ (void *)process_philo, &philos[i]);
+ if (result != 0)
+ break ;
+ i++;
+ }
+ while (data->simulation_running)
+ {
+ if (data->philos_must_eat <= 0)
+ data->simulation_running = 0;
+ }
+ while (i--)
+ {
+ pthread_join(philos[i].thread, NULL);
+ }
+ return (result);
}