philosophers

This commit is contained in:
Ladebeze66 2023-12-12 17:37:16 +01:00
commit d3e7bd98b5
13 changed files with 771 additions and 0 deletions

76
Makefile Executable file
View File

@ -0,0 +1,76 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2023/10/23 16:10:39 by fgras-ca #+# #+# #
# Updated: 2023/10/23 16:10:46 by fgras-ca ### ########.fr #
# #
# **************************************************************************** #
LOGO = @echo " __, ____, ____, ____, ____ ____, ___, ____,";\
echo "(-| (-/_| (-| \ (-|_, (-|__) (-|_, (- / (-|_,";\
echo " _|__, _/ |, _|__/ _|__, _|__) _|__, _/__, _|__,";\
echo "( ( ( ( ( ( ( ("
RST = \033[0m
GRAY = \033[0;90m
RED = \033[0;91m
GREEN = \033[0;92m
YELLOW = \033[0;93m
BLUE = \033[0;94m
MAGENTA = \033[0;95m
CYAN = \033[0;96m
WHITE = \033[0;97m
ORANGE = \033[38;5;214m
NAME = philo
SRCS = main.c \
threads.c \
initialize.c \
time.c \
philos.c \
utils.c \
memory.c \
routine.c \
forks.c \
monitoring.c \
OBJS = $(SRCS:.c=.o)
CC = gcc
RM = rm -f
CFLAGS = -Wall -Werror -Wextra -g
all: $(NAME)
$(NAME): $(OBJS)
@echo "$(RED)Compilation philosopher... $(RST)"
@$(CC) $(CFLAGS) $(OBJS) -o $(NAME) -lpthread
@echo "$(GREEN)Compilation complete. $(ORANGE)Type "./philo" for the menu!!$(RST)"
$(LOGO)
t : $(NAME)
@echo "$(RED)Compilation philosopher with fsanitize... $(RST)"
@$(CC) $(CFLAGS) -fsanitize=thread $(OBJS) -o $(NAME) -lpthread
@echo "$(GREEN)Compilation complete. $(ORANGE)Type "./philo" for the menu!!$(RST)"
$(LOGO)
clean:
@echo "$(RED)Deleating files objects... $(RST)"
@$(RM) $(OBJS)
@echo "$(GREEN)files deleted!! $(RST)"
$(LOGO)
fclean: clean
@echo "$(RED)Deleting program... $(RST)"
@$(RM) $(NAME)
@echo "$(GREEN)files deleted!! $(RST)"
$(LOGO)
re: fclean all
.PHONY: all t clean fclean re

291
en.subject.pdf Normal file
View File

@ -0,0 +1,291 @@
Philosophers
I never thought philosophy would be so deadly
Summary:
In this project, you will learn the basics of threading a process.
You will see how to create threads and you will discover mutexes.
Version: 11
Contents
I Introduction 2
II Common Instructions 3
III Overview 5
IV Global rules 6
V Mandatory part 8
VI Bonus part 9
VII Submission and peer-evaluation 10
1
Chapter I
Introduction
Philosophy (from Greek, philosophia, literally "love of wisdom") is the study of general
and fundamental questions about existence, knowledge, values, reason, mind, and lan-
guage. Such questions are often posed as problems to be studied or resolved. The term
was probably coined by Pythagoras (c. 570 495 BCE). Philosophical methods include
questioning, critical discussion, rational argument, and systematic presentation.
Classic philosophical questions include: Is it possible to know anything and to prove
it? What is most real? Philosophers also pose more practical and concrete questions such
as: Is there a best way to live? Is it better to be just or unjust (if one can get away with
it)? Do humans have free will?
Historically, "philosophy" encompassed any body of knowledge. From the time of An-
cient Greek philosopher Aristotle to the 19th century, "natural philosophy" encompassed
astronomy, medicine, and physics. For example, Newtons 1687 Mathematical Principles
of Natural Philosophy later became classified as a book of physics.
In the 19th century, the growth of modern research universities led academic philos-
ophy and other disciplines to professionalize and specialize. In the modern era, some
investigations that were traditionally part of philosophy became separate academic dis-
ciplines, including psychology, sociology, linguistics, and economics.
Other investigations closely related to art, science, politics, or other pursuits remained
part of philosophy. For example, is beauty objective or subjective? Are there many sci-
entific methods or just one? Is political utopia a hopeful dream or hopeless fantasy?
Major sub-fields of academic philosophy include metaphysics ("concerned with the fun-
damental nature of reality and being"), epistemology (about the "nature and grounds of
knowledge [and]... its limits and validity"), ethics, aesthetics, political philosophy, logic
and philosophy of science.
2
Chapter II
Common Instructions
• Your project must be written in C.
• Your project must be written in accordance with the Norm. If you have bonus
files/functions, they are included in the norm check and you will receive a 0 if there
is a norm error inside.
• Your functions should not quit unexpectedly (segmentation fault, bus error, double
free, etc) apart from undefined behaviors. If this happens, your project will be
considered non functional and will receive a 0 during the evaluation.
• All heap allocated memory space must be properly freed when necessary. No leaks
will be tolerated.
• If the subject requires it, you must submit a Makefile which will compile your
source files to the required output with the flags -Wall, -Wextra and -Werror, use
cc, and your Makefile must not relink.
• Your Makefile must at least contain the rules $(NAME), all, clean, fclean and
re.
• To turn in bonuses to your project, you must include a rule bonus to your Makefile,
which will add all the various headers, librairies or functions that are forbidden on
the main part of the project. Bonuses must be in a different file _bonus.{c/h} if
the subject does not specify anything else. Mandatory and bonus part evaluation
is done separately.
• If your project allows you to use your libft, you must copy its sources and its
associated Makefile in a libft folder with its associated Makefile. Your projects
Makefile must compile the library by using its Makefile, then compile the project.
• We encourage you to create test programs for your project even though this work
wont have to be submitted and wont be graded. It will give you a chance
to easily test your work and your peers work. You will find those tests especially
useful during your defence. Indeed, during defence, you are free to use your tests
and/or the tests of the peer you are evaluating.
• Submit your work to your assigned git repository. Only the work in the git reposi-
tory will be graded. If Deepthought is assigned to grade your work, it will be done
3
Philosophers I never thought philosophy would be so deadly
after your peer-evaluations. If an error happens in any section of your work during
Deepthoughts grading, the evaluation will stop.
4
Chapter III
Overview
Here are the things you need to know if you want to succeed this assignment:
• One or more philosophers sit at a round table.
There is a large bowl of spaghetti in the middle of the table.
• The philosophers alternatively eat, think, or sleep.
While they are eating, they are not thinking nor sleeping;
while thinking, they are not eating nor sleeping;
and, of course, while sleeping, they are not eating nor thinking.
• There are also forks on the table. There are as many forks as philosophers.
• Because serving and eating spaghetti with only one fork is very inconvenient, a
philosopher takes their right and their left forks to eat, one in each hand.
• When a philosopher has finished eating, they put their forks back on the table and
start sleeping. Once awake, they start thinking again. The simulation stops when
a philosopher dies of starvation.
• Every philosopher needs to eat and should never starve.
• Philosophers dont speak with each other.
• Philosophers dont know if another philosopher is about to die.
• No need to say that philosophers should avoid dying!
5
Chapter IV
Global rules
You have to write a program for the mandatory part and another one for the bonus part
(if you decide to do the bonus part). They both have to comply with the following rules:
• Global variables are forbidden!
• Your(s) program(s) should take the following arguments:
number_of_philosophers time_to_die time_to_eat time_to_sleep
[number_of_times_each_philosopher_must_eat]
◦ number_of_philosophers: The number of philosophers and also the number
of forks.
◦ time_to_die (in milliseconds): If a philosopher didnt start eating time_to_die
milliseconds since the beginning of their last meal or the beginning of the sim-
ulation, they die.
◦ time_to_eat (in milliseconds): The time it takes for a philosopher to eat.
During that time, they will need to hold two forks.
◦ time_to_sleep (in milliseconds): The time a philosopher will spend sleeping.
◦ number_of_times_each_philosopher_must_eat (optional argument): If all
philosophers have eaten at least number_of_times_each_philosopher_must_eat
times, the simulation stops. If not specified, the simulation stops when a
philosopher dies.
• Each philosopher has a number ranging from 1 to number_of_philosophers.
• Philosopher number 1 sits next to philosopher number number_of_philosophers.
Any other philosopher number N sits between philosopher number N - 1 and philoso-
pher number N + 1.
6
Philosophers I never thought philosophy would be so deadly
About the logs of your program:
• Any state change of a philosopher must be formatted as follows:
◦ timestamp_in_ms X has taken a fork
◦ timestamp_in_ms X is eating
◦ timestamp_in_ms X is sleeping
◦ timestamp_in_ms X is thinking
◦ timestamp_in_ms X died
Replace timestamp_in_ms with the current timestamp in milliseconds
and X with the philosopher number.
• A displayed state message should not be mixed up with another message.
• A message announcing a philosopher died should be displayed no more than 10 ms
after the actual death of the philosopher.
• Again, philosophers should avoid dying!
Your program must not have any data races.
7
Chapter V
Mandatory part
Program name philo
Turn in files Makefile, *.h, *.c, in directory philo/
Makefile NAME, all, clean, fclean, re
Arguments number_of_philosophers time_to_die time_to_eat
time_to_sleep
External functs. [number_of_times_each_philosopher_must_eat]
memset, printf, malloc, free, write,
Libft authorized usleep, gettimeofday, pthread_create,
Description pthread_detach, pthread_join, pthread_mutex_init,
pthread_mutex_destroy, pthread_mutex_lock,
pthread_mutex_unlock
No
Philosophers with threads and mutexes
The specific rules for the mandatory part are:
• Each philosopher should be a thread.
• There is one fork between each pair of philosophers. Therefore, if there are several
philosophers, each philosopher has a fork on their left side and a fork on their right
side. If there is only one philosopher, there should be only one fork on the table.
• To prevent philosophers from duplicating forks, you should protect the forks state
with a mutex for each of them.
8
Chapter VI
Bonus part
Program name philo_bonus
Turn in files Makefile, *.h, *.c, in directory philo_bonus/
Makefile NAME, all, clean, fclean, re
Arguments number_of_philosophers time_to_die time_to_eat
time_to_sleep
External functs. [number_of_times_each_philosopher_must_eat]
memset, printf, malloc, free, write, fork, kill,
Libft authorized exit, pthread_create, pthread_detach, pthread_join,
Description usleep, gettimeofday, waitpid, sem_open, sem_close,
sem_post, sem_wait, sem_unlink
No
Philosophers with processes and semaphores
The program of the bonus part takes the same arguments as the mandatory program.
It has to comply with the requirements of the Global rules chapter.
The specific rules for the bonus part are:
• All the forks are put in the middle of the table.
• They have no states in memory but the number of available forks is represented by
a semaphore.
• Each philosopher should be a process. But the main process should not be a
philosopher.
The bonus part will only be assessed if the mandatory part is
PERFECT. Perfect means the mandatory part has been integrally done
and works without malfunctioning. If you have not passed ALL the
mandatory requirements, your bonus part will not be evaluated at all.
9
Chapter VII
Submission and peer-evaluation
Turn in your assignment in your Git repository as usual. Only the work inside your repos-
itory will be evaluated during the defense. Dont hesitate to double check the names of
your files to ensure they are correct.
Mandatory part directory: philo/
Bonus part directory: philo_bonus/
V L ( Lp aW 8
) * q fx 2 u L 5 kt 6 ::/ .
? p x >g 0 Jb n R V
7 vo
v c pt g j
S 4 H .
I 6 <)
A2 5 ) E ? d
B f - Z
*v
, ;I I
sC:
10

69
forks.c Executable file
View File

@ -0,0 +1,69 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* forks.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 11:50:15 by fgras-ca #+# #+# */
/* Updated: 2023/10/23 16:09:52 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
static void single_philosopher(t_philo *philo)
{
pthread_mutex_lock(&philo->left_fork->mutex_fork);
print_action(philo, BLUE"has taken a fork🍴"RST, 0);
while (1)
{
pthread_mutex_lock(&philo->sim->end_mutex);
if (philo->sim->is_philosopher_dead)
{
pthread_mutex_unlock(&philo->sim->end_mutex);
break ;
}
pthread_mutex_unlock(&philo->sim->end_mutex);
}
pthread_mutex_unlock(&philo->left_fork->mutex_fork);
}
void take_forks(t_philo *philo)
{
if (philo->sim->num_philosophers == 1)
{
single_philosopher(philo);
return ;
}
usleep(300);
if (philo->id % 2 == 0)
{
pthread_mutex_lock(&philo->left_fork->mutex_fork);
print_action(philo, BLUE"has taken a fork🍴"RST, 0);
pthread_mutex_lock(&philo->right_fork->mutex_fork);
print_action(philo, BLUE"has taken a fork🍴"RST, 0);
}
else
{
pthread_mutex_lock(&philo->right_fork->mutex_fork);
print_action(philo, BLUE"has taken a fork🍴"RST, 0);
pthread_mutex_lock(&philo->left_fork->mutex_fork);
print_action(philo, BLUE"has taken a fork🍴"RST, 0);
}
philo->can_eat = 1;
}
void release_forks(t_philo *philo)
{
if (philo->can_eat)
{
pthread_mutex_unlock(&philo->left_fork->mutex_fork);
if (philo->sim->num_philosophers > 1)
{
pthread_mutex_unlock(&philo->right_fork->mutex_fork);
}
philo->can_eat = 0;
}
usleep(300);
}

60
initialize.c Executable file
View File

@ -0,0 +1,60 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* initialize.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 11:54:03 by fgras-ca #+# #+# */
/* Updated: 2023/10/17 12:27:25 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
int initialize_default_values(t_simulation *sim)
{
sim->num_philosophers = 0;
sim->time_to_die = 0;
sim->time_to_eat = 0;
sim->time_to_sleep = 0;
sim->max_meals = 0;
sim->start_time = initialize_start_time();
sim->is_philosopher_dead = 0;
sim->simulation_end = 0;
pthread_mutex_init(&sim->print_mutex, NULL);
pthread_mutex_init(&sim->end_mutex, NULL);
return (0);
}
int args_values(t_simulation *sim, int argc, char **argv)
{
if (argc < 5 || argc > 6)
{
pthread_mutex_lock(&sim->print_mutex);
printf(RED"Usage: %s num_philosophers time_to_die "
"time_to_eat time_to_sleep [max_meals]\n" RST, argv[0]);
pthread_mutex_unlock(&sim->print_mutex);
exit (EXIT_FAILURE);
}
else
{
sim->num_philosophers = ft_atoi(argv[1]);
sim->time_to_die = ft_atoi(argv[2]);
sim->time_to_eat = ft_atoi(argv[3]);
sim->time_to_sleep = ft_atoi(argv[4]);
if (argc == 6)
{
sim->max_meals = ft_atoi(argv[5]);
}
}
return (0);
}
int initialize_simulation(t_simulation *sim, int argc, char **argv)
{
initialize_default_values(sim);
args_values(sim, argc, argv);
initialize_philosophers(sim);
return (0);
}

23
main.c Executable file
View File

@ -0,0 +1,23 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 12:28:04 by fgras-ca #+# #+# */
/* Updated: 2023/10/17 12:29:50 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
int main(int argc, char **argv)
{
t_simulation sim;
initialize_simulation(&sim, argc, argv);
join_threads(&sim);
cleanup(&sim);
return (0);
}

44
memory.c Executable file
View File

@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* clean.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 11:45:37 by fgras-ca #+# #+# */
/* Updated: 2023/10/17 11:48:26 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
int allocate_memory(t_simulation *sim)
{
sim->forks = ft_calloc(sim->num_philosophers, sizeof(t_fork));
if (!sim->forks)
return (-1);
sim->philos = ft_calloc(sim->num_philosophers, sizeof(t_philo));
if (!sim->philos)
{
free(sim->forks);
return (-1);
}
return (0);
}
void cleanup(t_simulation *sim)
{
int i;
i = 0;
while (i < sim->num_philosophers)
{
pthread_mutex_destroy(&sim->forks[i].mutex_fork);
pthread_mutex_destroy(&sim->philos[i].eating_mutex);
i++;
}
free(sim->philos);
free(sim->forks);
pthread_mutex_destroy(&sim->end_mutex);
pthread_mutex_destroy(&sim->print_mutex);
}

106
monitoring.c Executable file
View File

@ -0,0 +1,106 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* monitoring.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 12:32:18 by fgras-ca #+# #+# */
/* Updated: 2023/10/23 16:22:19 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
int check_philosopher_death(t_philo *philo)
{
long time_since_last_meal;
pthread_mutex_lock(&philo->eating_mutex);
time_since_last_meal = get_time(philo->sim->start_time)
- philo->last_meal_time;
if (time_since_last_meal <= philo->sim->time_to_die)
{
pthread_mutex_unlock(&philo->eating_mutex);
return (0);
}
pthread_mutex_unlock(&philo->eating_mutex);
pthread_mutex_lock(&philo->sim->end_mutex);
if (!philo->sim->is_philosopher_dead)
{
philo->sim->is_philosopher_dead = 1;
pthread_mutex_unlock(&philo->sim->end_mutex);
print_action(philo, RED"died☠" RST, 1);
return (1);
}
pthread_mutex_unlock(&philo->sim->end_mutex);
return (0);
}
static int all_philosophers_have_eaten_required_meals(t_simulation *sim)
{
int i;
i = 0;
while (i < sim->num_philosophers)
{
if (sim->philos[i].meals_eaten < sim->max_meals)
{
return (0);
}
i++;
}
return (1);
}
static int handle_all_philosophers_ate(t_philo *philo)
{
if (!philo->sim->simulation_end)
{
philo->sim->simulation_end = 1;
printf(RED"ALL PHILOSOPHERS EAT %d MEALS!!"RST"\n",
philo->sim->max_meals);
print_action(philo, NULL, 1);
return (1);
}
return (0);
}
static int check_max_meals(t_philo *philo)
{
if (philo->sim->max_meals == 0)
{
return (0);
}
pthread_mutex_lock(&philo->sim->end_mutex);
if (all_philosophers_have_eaten_required_meals(philo->sim))
{
pthread_mutex_unlock(&philo->sim->end_mutex);
return (handle_all_philosophers_ate(philo));
}
pthread_mutex_unlock(&philo->sim->end_mutex);
return (0);
}
void *philo_monitor(void *arg)
{
t_philo *philo;
int dead;
int simulation_end;
philo = (t_philo *)arg;
while (1)
{
pthread_mutex_lock(&philo->sim->end_mutex);
dead = philo->sim->is_philosopher_dead;
simulation_end = philo->sim->simulation_end;
pthread_mutex_unlock(&philo->sim->end_mutex);
if (dead || simulation_end)
break ;
if (check_philosopher_death(philo))
return (NULL);
if (check_max_meals(philo))
return (NULL);
}
return (NULL);
}

91
philo.h Executable file
View File

@ -0,0 +1,91 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philo.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/12 10:44:03 by fgras-ca #+# #+# */
/* Updated: 2023/10/23 16:29:16 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PHILO_H
# define PHILO_H
# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <sys/time.h>
# include <pthread.h>
# include <limits.h>
# define RST "\033[0;39m"
# define GRAY "\033[0;90m"
# define RED "\033[0;91m"
# define GREEN "\033[0;92m"
# define YELLOW "\033[0;93m"
# define BLUE "\033[0;94m"
# define MAGENTA "\033[0;95m"
# define CYAN "\033[0;96m"
# define WHITE "\033[0;97m"
# define ORANGE "\033[38;5;214m"
typedef struct s_simulation t_simulation;
typedef struct s_fork
{
pthread_mutex_t mutex_fork;
} t_fork;
typedef struct s_philo
{
int id;
int meals_eaten;
int can_eat;
long last_meal_time;
t_fork *left_fork;
t_fork *right_fork;
pthread_t thread;
pthread_t philosopher_monitor;
pthread_mutex_t eating_mutex;
t_simulation *sim;
} t_philo;
typedef struct s_simulation
{
int num_philosophers;
int time_to_die;
int time_to_eat;
int time_to_sleep;
int max_meals;
long start_time;
t_philo *philos;
t_fork *forks;
volatile int is_philosopher_dead;
volatile int simulation_end;
pthread_mutex_t print_mutex;
pthread_mutex_t end_mutex;
} t_simulation;
int initialize_simulation(t_simulation *sim, int argc, char **argv);
int initialize_philosophers(t_simulation *sim);
int ft_atoi(const char *nptr);
int init_threads(t_simulation *sim);
int join_threads(t_simulation *sim);
int args_values(t_simulation *sim, int argc, char **argv);
int initialize_default_values(t_simulation *sim);
int allocate_memory(t_simulation *sim);
long initialize_start_time(void);
long get_time(long start_time);
void *philosopher_life(void *arg);
void cleanup(t_simulation *sim);
void take_forks(t_philo *philo);
void release_forks(t_philo *philo);
void print_action(t_philo *philo, char *action, int death_action);
void eat(t_philo *philo);
void think(t_philo *philo);
void *philo_monitor(void *arg);
void *ft_calloc(size_t nmemb, size_t size);
#endif

38
philos.c Executable file
View File

@ -0,0 +1,38 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* philos.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 14:31:06 by fgras-ca #+# #+# */
/* Updated: 2023/10/17 15:05:24 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
int initialize_philosophers(t_simulation *sim)
{
int i;
i = 0;
if (allocate_memory(sim) < 0)
return (-1);
while (i < sim->num_philosophers)
{
sim->philos[i].id = i + 1;
pthread_mutex_init(&sim->forks[i].mutex_fork, NULL);
sim->philos[i].left_fork = &sim->forks[i];
sim->philos[i].right_fork = &sim->forks[(i + 1)
% sim->num_philosophers];
sim->philos[i].sim = sim;
sim->philos[i].meals_eaten = 0;
sim->philos[i].can_eat = 0;
sim->philos[i].last_meal_time = get_time(sim->start_time);
pthread_mutex_init(&sim->philos[i].eating_mutex, NULL);
i++;
}
init_threads(sim);
return (0);
}

73
routine.c Executable file
View File

@ -0,0 +1,73 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* routine.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 15:20:10 by fgras-ca #+# #+# */
/* Updated: 2023/10/23 16:27:02 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
void eat(t_philo *philo)
{
pthread_mutex_lock(&philo->eating_mutex);
if (get_time(philo->sim->start_time)
- philo->last_meal_time > philo->sim->time_to_die)
{
pthread_mutex_unlock(&philo->eating_mutex);
return ;
}
if (!philo->can_eat)
{
pthread_mutex_unlock(&philo->eating_mutex);
return ;
}
philo->last_meal_time = get_time(philo->sim->start_time);
philo->meals_eaten++;
usleep(philo->sim->time_to_eat * 1000);
pthread_mutex_unlock(&philo->eating_mutex);
usleep(300);
}
void philo_sleep(t_philo *philo)
{
philo->can_eat = 0;
usleep(philo->sim->time_to_sleep * 1000);
}
void think(t_philo *philo)
{
philo->can_eat = 0;
}
void *philosopher_life(void *arg)
{
t_philo *philo;
int continue_running;
philo = (t_philo *)arg;
continue_running = 1;
while (continue_running)
{
pthread_mutex_lock(&philo->sim->end_mutex);
continue_running = !philo->sim->is_philosopher_dead
&& !philo->sim->simulation_end;
pthread_mutex_unlock(&philo->sim->end_mutex);
if (!continue_running)
break ;
take_forks(philo);
print_action(philo, GREEN"is eating😋"RST, 0);
eat(philo);
release_forks(philo);
philo->can_eat = 0;
print_action(philo, ORANGE"is sleeping😴"RST, 0);
usleep(philo->sim->time_to_sleep * 1000);
print_action(philo, CYAN"is thinking🤔" RST, 0);
think(philo);
}
return (NULL);
}

72
threads.c Executable file
View File

@ -0,0 +1,72 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* threads.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/12 10:45:20 by fgras-ca #+# #+# */
/* Updated: 2023/10/23 16:28:10 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
static int create_philosopher_threads(t_simulation *sim)
{
int i;
i = 0;
while (i < sim->num_philosophers)
{
if (i % 2 == 0)
pthread_create(&sim->philos[i].thread, NULL,
philosopher_life, &sim->philos[i]);
else
pthread_create(&sim->philos[i].thread, NULL,
philosopher_life, &sim->philos[i]);
i++;
}
return (1);
}
static int create_monitoring_threads(t_simulation *sim)
{
int i;
i = 0;
while (i < sim->num_philosophers)
{
if (i % 2 == 0)
pthread_create(&sim->philos[i].philosopher_monitor, NULL,
philo_monitor, &sim->philos[i]);
else
pthread_create(&sim->philos[i].philosopher_monitor, NULL,
philo_monitor, &sim->philos[i]);
i++;
}
return (1);
}
int init_threads(t_simulation *sim)
{
if (!create_philosopher_threads(sim))
return (0);
if (!create_monitoring_threads(sim))
return (0);
return (1);
}
int join_threads(t_simulation *sim)
{
int i;
i = 0;
while (i < sim->num_philosophers)
{
pthread_join(sim->philos[i].philosopher_monitor, NULL);
pthread_join(sim->philos[i].thread, NULL);
i++;
}
return (1);
}

29
time.c Executable file
View File

@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* time.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 15:31:00 by fgras-ca #+# #+# */
/* Updated: 2023/10/17 16:20:32 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
long initialize_start_time(void)
{
struct timeval now;
gettimeofday(&now, NULL);
return ((now.tv_sec * 1000) + (now.tv_usec / 1000));
}
long get_time(long start_time)
{
struct timeval now;
gettimeofday(&now, NULL);
return (((now.tv_sec * 1000) + (now.tv_usec / 1000)) - start_time);
}

90
utils.c Executable file
View File

@ -0,0 +1,90 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/17 16:21:02 by fgras-ca #+# #+# */
/* Updated: 2023/10/17 16:27:28 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "philo.h"
static void ft_bzero(void *ptr, size_t len)
{
size_t i;
i = 0;
while (i < len)
{
*(char *)(ptr + i) = 0;
i++;
}
}
void *ft_calloc(size_t nmemb, size_t size)
{
void *ptr;
if (!nmemb || !size)
return (malloc(0));
if ((nmemb * size) / size != nmemb)
return (NULL);
ptr = malloc(size * nmemb);
if (!ptr)
return (0);
ft_bzero(ptr, size * nmemb);
return (ptr);
}
int ft_atoi(const char *nptr)
{
int i;
int sign;
int res;
i = 0;
sign = 1;
res = 0;
while (nptr[i] == 32 || (nptr[i] >= 9 && nptr[i] <= 13))
i++;
if (nptr[i] == '-' || nptr[i] == '+')
{
if (nptr[i] == '-')
sign = - (1);
i++;
}
while (nptr[i] >= 48 && nptr[i] <= 57)
{
res = res * 10 + nptr[i] - 48;
i++;
}
return (res * sign);
}
void print_action(t_philo *philo, char *action, int death_action)
{
t_simulation *sim;
int is_dead;
int all_eat;
sim = philo->sim;
pthread_mutex_lock(&sim->print_mutex);
pthread_mutex_lock(&sim->end_mutex);
is_dead = sim->is_philosopher_dead;
all_eat = sim->simulation_end;
pthread_mutex_unlock(&sim->end_mutex);
if ((is_dead || all_eat) && !death_action)
{
pthread_mutex_unlock(&sim->print_mutex);
return ;
}
if (action)
{
printf("%ld ms"YELLOW" %d %s\n", get_time(sim->start_time),
philo->id, action);
}
pthread_mutex_unlock(&sim->print_mutex);
}