/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   launch.c                                           :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: hulamy <hulamy@student.42.fr>              +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2022/01/26 15:30:49 by hulamy            #+#    #+#             */
/*   Updated: 2022/02/01 23:44:28 by hulamy           ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "philo.h"

static int	is_finished(t_philo *philo, struct timeval *stime)
{
	long int		time_stamp;
	int				time;

	if (philo->global->satiated_count == philo->params->n_phi)
	{
		pthread_mutex_lock(&(philo->global->m_stop));
		philo->global->stop = 1;
		pthread_mutex_unlock(&(philo->global->m_stop));
		return (1);
	}
	time = diff_time(philo, stime);
	if (time >= philo->params->t_die)
	{
		pthread_mutex_lock(&(philo->global->m_print));
		philo->global->stop = 1;
		time_stamp = (stime->tv_sec - philo->global->t_start.ts) * 1000;
		time_stamp += (stime->tv_usec - philo->global->t_start.tu) / 1000;
		printf("%s%li %i died%s\n", B_RED, time_stamp, philo->p_nbr, RESET);
		pthread_mutex_unlock(&(philo->global->m_print));
		return (1);
	}
	return (0);
}

int	is_satiated(t_philo *philo)
{
	pthread_mutex_lock(&(philo->m_eat));
	if (philo->eat_count == philo->params->n_eat)
	{
		philo->global->satiated_count++;
		pthread_mutex_unlock(&(philo->m_eat));
		return (1);
	}
	pthread_mutex_unlock(&(philo->m_eat));
	return (0);
}

static void	pere_fouettard(t_philo *philo)
{
	struct timeval	stime;
	int				i;
	int				satiated;

	while (philo->global->stop == 0)
	{
		i = 0;
		satiated = 1;
		gettimeofday(&stime, NULL);
		while (i < philo->params->n_phi)
		{
			if (satiated == 1 && is_satiated(philo) == 0)
				satiated = 0;
			if (is_finished(philo, &stime))
				break ;
			philo = philo->next;
			i++;
		}
		usleep(1 * 1000);
	}
}

void	launch(t_philo *philo, pthread_t *id)
{
	int	i;

	i = 0;
	while (i < philo->params->n_phi)
	{
		pthread_create(&id[i], NULL, &philo_exec, philo);
		philo = philo->next;
		i++;
	}
	pere_fouettard(philo);
}
