#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define N 3 /*posti in bagno*/

static sem_t mutex1,mutex2 /*c'è una donna in bagno*/,mutex3/*c'è un uomo in bagno*/;
static sem_t uomini,donne;
int donne_in_bagno=0, uomini_in_bagno=0; //quante persone in bagno

void *uomo(void *arg)
{
	if (donne_in_bagno>0)
	{
		printf("Ci sono delle donne in bagno, l'uomo aspetta\n");
		sem_wait(&mutex2);
	}
	//sem_wait(&mutex2);
	printf("Non ci sono donne in bagno\n");
	sem_wait(&uomini);
	printf("C'e' spazio per un altro uomo\n");
	if (uomini_in_bagno==0)
		sem_wait(&mutex3);
	uomini_in_bagno++;
	printf("L'uomo va in bagno: TOT = %d\n", uomini_in_bagno);
	sleep(3);
	sem_post(&uomini);
	uomini_in_bagno--;
	printf("L'uomo esce\n");
	if (uomini_in_bagno==0)
	{
		sem_post(&mutex3);
	}

	pthread_exit(0);
}

void *donna(void *arg)
{
	if (uomini_in_bagno>0)
	{
		printf("Ci sono uomini in bagno: la donna aspetta\n");
		sem_wait(&uomini);
	}
	//printf("Donna in cerca del bagno\n");
	sem_wait(&mutex2); //occupato dalle donne
	donne_in_bagno++;
	//printf("Non ci sono uomini in bagno, la donna entra\n");
	//sem_post(&mutex2);
	sem_wait(&donne);
	printf("La donna va in bagno: TOT = %d\n", donne_in_bagno);
	//sleep(1);
	sem_post(&donne);
	donne_in_bagno--;
	if (donne_in_bagno==0)
	{
		sem_post(&mutex2); //liberiamo dalle donne
		//sem_post(&uomini);
	}
	printf("La donna esce\n");
	//sem_post(&mutex2);
	pthread_exit(0);
}

int main(void)
{
	pthread_t th1, th2, th3, th4,th5;
	int retcode;
	sem_init(&uomini,0,N);
	sem_init(&donne,0,N);
	sem_init(&mutex1,0,1);
	sem_init(&mutex2,0,1);
	sem_init(&mutex3,0,1);
	
	
	if(pthread_create(&th1,NULL,uomo,NULL)<0)
	{
		fprintf(stderr,"pthread_create error for thread 1 (uomo)\n");
		exit(1);
	}
	if(pthread_create(&th2,NULL,uomo,NULL)<0)
	{
		fprintf(stderr,"pthread_create error for thread 2 (donna)\n");
		exit(1);
	}
	if(pthread_create(&th3,NULL,uomo,NULL)<0)
	{
		fprintf(stderr,"pthread_create error for thread 3 (donna)\n");
		exit(1);
	}
	if(pthread_create(&th4,NULL,uomo,NULL)<0)
	{
		fprintf(stderr,"pthread_create error for thread 4 (uomo)\n");
		exit(1);
	}
	if(pthread_create(&th5,NULL,uomo,NULL)<0)
	{
		fprintf(stderr,"pthread_create error for thread 5 (donna)\n");
		exit(1);
	}
		

	retcode = pthread_join(th3,NULL);
	if (retcode!=0)
		fprintf(stderr,"join fallito %d\n", retcode);
	else
		printf("Terminato il thread 3\n");
	retcode = pthread_join(th4,NULL);
	if (retcode!=0)
		fprintf(stderr,"join fallito %d\n", retcode);
	else
		printf("Terminato il thread 4\n");
	retcode = pthread_join(th5,NULL);
	if (retcode!=0)
		fprintf(stderr,"join fallito %d\n", retcode);
	else
		printf("Terminato il thread 5\n");
	retcode = pthread_join(th1,NULL);
	if (retcode!=0)
		fprintf(stderr,"join fallito %d\n", retcode);
	else
		printf("Terminato il thread 1\n");

	retcode = pthread_join(th2,NULL);
	if (retcode!=0)
		fprintf(stderr,"join fallito %d\n", retcode);
	else
		printf("Terminato il thread 2\n");
	return 0;
}
 
