#include <stddef.h>
#include <stdlib.h>
+static void init_philo(t_diner *diner, t_philo *philo,
+ t_fork *fork1, t_fork *fork2)
+{
+ philo->forks[0] = fork1;
+ philo->forks[1] = fork2;
+ philo->settings = &diner->setting;
+ philo->last_eaten = 0;
+ philo->num_eaten = 0;
+ return ;
+}
+
// Shortcircuiting does no harm here as when any mutex_init fails
// the program will end anyway.
int init(t_diner *diner, pthread_t **threads)
i = 0;
while (i < count)
{
- init_mutex(diner->forks + i, NULL);
+ init_mutex(&diner->forks[i].lock, NULL);
+ diner->forks[i].is_taken = 0;
init_mutex(&diner->philos[i].philo_lock, NULL);
- diner->philos[i].forks[i % 2] = diner->forks + i;
- diner->philos[i].forks[(i + 1) % 2] = diner->forks
- + (i + 1) % count;
- diner->philos[i].settings = &diner->setting;
- diner->philos[i].last_eaten = 0;
+ init_philo(diner, diner->philos + i,
+ diner->forks + i, diner->forks + (i + 1) % count);
diner->philos[i].id = i + 1;
- diner->philos[i].num_eaten = 0;
++i;
}
return (!all_mutexes_initialized(diner));
i = 0;
if (diner->forks)
while (i < count)
- destroy_mutex(diner->forks + (i++));
+ destroy_mutex(&diner->forks[i++].lock);
destroy_mutex(&diner->setting.terminal_lock);
destroy_mutex(&diner->setting.end_lock);
free(diner->philos);
i = 0;
while (i < diner->setting.philo_count)
{
- res = res && diner->forks[i].is_init;
+ res = res && diner->forks[i].lock.is_init;
res = res && diner->philos[i].philo_lock.is_init;
++i;
}
return ;
}
-static void philo_eat(t_philo *philo)
+static void take_forks(t_philo *philo)
{
- mutex_lock(philo->forks[0]);
- if (report(philo, "has taken a fork"))
+ int i;
+ int forks_taken;
+
+ i = 0;
+ forks_taken = 0;
+ while (forks_taken < 2 && !end(philo->settings))
{
- mutex_unlock(philo->forks[0]);
- return ;
+ mutex_lock(&philo->forks[i]->lock);
+ if (philo->forks[i]->is_taken)
+ {
+ mutex_unlock(&philo->forks[i]->lock);
+ if (forks_taken)
+ {
+ mutex_lock(&philo->forks[!i]->lock);
+ philo->forks[!i]->is_taken = 0;
+ mutex_unlock(&philo->forks[!i]->lock);
+ forks_taken = 0;
+ }
+ usleep(100);
+ continue ;
+ }
+ philo->forks[i]->is_taken = 1;
+ mutex_unlock(&philo->forks[i]->lock);
+ ++forks_taken;
+ i = !i;
}
- mutex_lock(philo->forks[1]);
+ return ;
+}
+
+static void philo_eat(t_philo *philo)
+{
+ take_forks(philo);
+ report(philo, "has taken a fork");
report(philo, "has taken a fork");
mutex_lock(&philo->philo_lock);
philo->last_eaten = usecs_since_start(philo->settings->start);
mutex_unlock(&philo->philo_lock);
if (!report(philo, "is eating"))
usleep(philo->settings->time_to_eat);
- mutex_unlock(philo->forks[0]);
- mutex_unlock(philo->forks[1]);
+ mutex_lock(&philo->forks[0]->lock);
+ philo->forks[0]->is_taken = 0;
+ mutex_unlock(&philo->forks[0]->lock);
+ mutex_lock(&philo->forks[1]->lock);
+ philo->forks[1]->is_taken = 0;
+ mutex_unlock(&philo->forks[1]->lock);
return ;
}
t_mutex end_lock;
} t_settings;
+typedef struct s_fork
+{
+ int is_taken;
+ t_mutex lock;
+} t_fork;
+
typedef struct s_philosopher
{
unsigned int num_eaten;
size_t id;
useconds_t last_eaten;
t_settings *settings;
- t_mutex *forks[2];
+ t_fork *forks[2];
t_mutex philo_lock;
} t_philo;
{
t_settings setting;
t_philo *philos;
- t_mutex *forks;
+ t_fork *forks;
} t_diner;
enum e_end