/* Compito 180508	
	4 thread si comportano alternativamente 2 volte come consumatori e 2 volte come produttori.
	coda circolare di 20 elementi, ogni elemento contiene un contatore per il numero di volte che agisce il produttore e il PID del produttore
	Il produttore inserisce un elemento alla volta e stampa a video un messaggio di creazione
	Il consumatore consuma un elemento alla volta e stampa a video quanto consumato 
vado a memoria con il testo. dovrebbe essere corretto l'ho fatto controllare ad un assistente della prof
vito muccapazza[at]gmail[dot]com*/
	
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define DIM 20
#define NT 4
typedef struct {
	int contatore,TID,info;
}cosa;
typedef struct {
	int testa,coda,n_dati;
	cosa* dato;
	}coda_t;
int inizializza (coda_t *c) {
	c->testa=c->coda=c->n_dati;
	c->dato=(cosa*)malloc((sizeof(cosa*)*DIM));
	return (c->dato == NULL) ? 1:0;
}
int inserisci (coda_t *c, cosa elemento) {
	if (c->n_dati<DIM) {
		c->dato[c->testa]=elemento;
		c->testa=(c->testa+1)%DIM;
		c->n_dati++;
		return 0;
	} 	
	return 1;
}
	
int estrai (coda_t *c, cosa *elemento) {
	if (c->n_dati>0) {
		*elemento=c->dato[c->coda];
		c->coda=(c->coda+1)%DIM;
		c->n_dati--;
		return 0;
	}
	return 1;
}
pthread_mutex_t mutex;
pthread_cond_t cond1,cond2;
coda_t buffer;
int cont=0;
int flag=0;

void* thread () {
	int i;
	cosa aux;
	int inserito=0;
	//int estratto=0;
		while (1) { 
		for (i=0;i<2;i++) {
			pthread_mutex_lock (&mutex);
			while (inserito==DIM) {
			printf("\nSono il produttore %d, la coda è piena e resto in attesa",(int)pthread_self());
			pthread_cond_wait (&cond1,&mutex);
			}
			int rnd=rand()%100;
			cont++;
			aux.contatore=cont;
			aux.TID=(int)pthread_self();
			aux.info=rnd;
			inserisci (&buffer,aux);
			
			inserito++;
			printf("\nProduttore %d, ho scritto in coda l'elemento %d",(int)pthread_self(),aux.info);
			/*if (inserito==DIM) {
			flag=1;
			inserito=0; // ????
			
			}*/
			pthread_cond_signal (&cond2);
			pthread_mutex_unlock (&mutex);
			sleep(1+rand()%3);
			}
		for (i=0;i<2;i++) {
			pthread_mutex_lock (&mutex);
			while (inserito==0) { //????
			printf("\nSono il consumatore %d, la coda è vuota e resto in attesa",(int)pthread_self());
			pthread_cond_wait (&cond2,&mutex);
			}
			estrai (&buffer,&aux);
			printf("\nElementi estratti da %d contatore->%d, TID->%d, elemento->%d",(int)pthread_self(),aux.contatore,aux.TID,aux.info);
			
			inserito--; //????
			/*if (estratto==DIM) {
			flag=2;
			estratto=0;
			
			}*/
			pthread_cond_signal (&cond1);
			pthread_mutex_unlock (&mutex);
			
			}
			sleep(1+rand()%5);
			}//fine while 
		}
			
			
int main () {
 int i;
 pthread_t th[NT];

 pthread_mutex_init(&mutex,NULL);
 pthread_cond_init(&cond1,NULL); // quando e' vuota ()
 pthread_cond_init(&cond2,NULL); // quando e' piena ()


inizializza(&buffer);
 
for (i=0;i<NT;++i) {
 pthread_create(&th[i],NULL,thread,NULL);
 printf("thread %d creato\n", i );
}
pthread_exit (NULL);
 return 0;
}
