Skip to content

Latest commit

 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

What is this all about?

The Dining Philosophers Problem is a classic computing challenge that illustrates the problems of synchronization and resource management in shared systems, but with a little twist on 42 STYLE. It involves N number of philosophers sitting at a round table, alternating between eating, sleeping and thinking.

Each philosopher needs two forks to eat, but if everyone takes the fork to their left simultaneously, a deadlock can occur, since no philosopher can eat without the fork to their right. Solutions to this problem aim to avoid deadlocks by ensuring that philosophers share forks in a coordinated way, usually using semaphores or mutexes to control access to resources.


How can I test it?

I'm glad you asked! The process is very simple.


1º Step - Download the files:

git clone https://github.com/brennm2/philo.git && cd philo

2º Step - Compiling the program

cd philo
make

3º Step - Running the program!

Now you need to put in the following inputs:

./philo NUMBER_OF_PHILO TIME_TO_DIE TIME_TO_EAT TIME_TO_SLEEP

NUMBER_OF_PHILO = Number of philosophers that is sitting on the table
TIME_TO_DIE = Time, in milliseconds, that philosophers can die
TIME_TO_EAT = Time, in milliseconds, that philosophers can eat
TIME_TO_SLEEP = Time, in milliseconds, that philosophers can sleep
NUMBER_OF_MEALS = How many meals that all philosophers have to eat to end the program (this one is optional)

Here is an example:

./philo 5 800 200 200

or, if you want to set a limit of meals

./philo 5 800 200 200 5



Considerations and Explanations

--------- Soft Locking when sleeping ---------


Sometimes, if you set the sleep value too high, the program can get stuck in a state and not finish.
For example 5 800 200 200000

Then you ask yourself, "How can this happen?", well...

The problem is that one philosopher dies, because enough time has passed for him to die, but another philosopher keeps sleeping for 200000ms. This causes a soft lock in the program, and it doesn't finish, since one philosopher has died.

Example and solution (on details):

Details

Well, the solution is a simple one, when you run your custom usleep function, you have to check if someone has died.

I did like this:

int	ft_check_sleep(t_philo *philo)
{
	if (*philo->dead == 1)
		return (1);
	return (0);
}

void	ft_usleep(size_t milsecond, t_philo *philo)
{
	size_t	start_time;

	start_time = get_time();
	while ((get_time() - start_time) < milsecond && ft_check_sleep(philo) == 0)
	{
		usleep(500);
	}
}

--------- MY deadlock with forks ---------


Let's assume you already know what deadlock is and how to find it with -fsanitize=thread (If you don't, try asking the friend next to you ;) ) Then you run the program with the fsanitize flag end... Oh no, deadlocks. I'll tell you how I solved my problem with that.

The funny thing is that it was actually "easy" to solve. My problem was that all the philosophers were trying to take the same fork at the same time, which obviously caused a deadlock.

What I did to solve it was, IF the philosopher is even, he takes the fork on the RIGHT and then takes the one on the LEFT.
And if it's odd, it takes the one on the LEFT and then the one on the RIGHT.

Example and solution (on details):

Details

Here how I did it (Keep in mind, fsanitize can break your timings):

if (philos->id % 2 == 0)
	{
		pthread_mutex_lock(philos->right_fork);
		glados_speak(C_CYAN"has taken a fork"END_COLOR, philos, philos->id);
		pthread_mutex_lock(philos->left_fork);
	}
	else
	{
		pthread_mutex_lock(philos->left_fork);
		glados_speak(C_CYAN"has taken a fork"END_COLOR, philos, philos->id);
		pthread_mutex_lock(philos->right_fork);
	}

--------- Low sleep time and odd number ---------


If you used my solution for deadlocks (or a similar one), now your philosophers can die randomly if the number of philosophers is odd and the sleeping time is short, for example ./philo 5 800 200 100

Then, again, you ask yourself, "WHATT?", well...

It's OK, we can fix it. Again, the problem is with the odd numbers. So, to fix it, we need to set a condition on the ft_think function.

Example and solution (on details):

Details

We need to find the right time for the philosopher, if necessary, to think. We can do this: (time to eat * 2) - time to sleep
You can do like this:

if (philos->number_of_philosopher % 2 != 0)
		ft_usleep((philos->time_to_eat * 2) - philos->time_to_sleep, philos)

--------- Philosophers stealing food ---------


Sometimes, a philosopher can die randomly, and this can be caused by one of the philosophers “stealing” the turn of another who is waiting.

For example: Philo 1 has just eaten and is going to sleep. Philo 3 is waiting for someone to release the forks so he can eat. Then Philo 1 wakes up and grabs the forks before Philo 3, who ends up dying.

The solution is quite simple. Just set the ft_usleep function to 1ms in the ft_think function. This would be ft_usleep(1). This gives Philo 3 enough time to pick up the forks and leave Philo 1 to think.

42 Rules


In every project we must follow certain rules, here are the rules for this project:

- The project must not have memory leaks
- The project must use the flags -Wall -Wextra -Werror
- Each function can have a maximum of 25 lines
- Each file should only have 5 functions
- We should keep the code as clean as possible, for example, declarations should be on separate lines
- We cannot use "for", "do...while", "switch", "case", "goto", ternary operators, or variable-length arrays


Credits

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages