mirror of
https://github.com/Ladebeze66/philosophers.git
synced 2025-12-15 13:46:59 +01:00
philosophers
This commit is contained in:
commit
d3e7bd98b5
76
Makefile
Executable file
76
Makefile
Executable 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
291
en.subject.pdf
Normal 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, Newton’s 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 project’s
|
||||
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
|
||||
won’t have to be submitted and won’t 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
|
||||
Deepthought’s 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 don’t speak with each other.
|
||||
• Philosophers don’t 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 didn’t 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. Don’t 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
69
forks.c
Executable 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
60
initialize.c
Executable 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
23
main.c
Executable 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
44
memory.c
Executable 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
106
monitoring.c
Executable 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
91
philo.h
Executable 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
38
philos.c
Executable 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
73
routine.c
Executable 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
72
threads.c
Executable 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
29
time.c
Executable 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
90
utils.c
Executable 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);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user