/* 
 * Campeonato entre 4 threads para entrada na regiao critica
 */

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int s = 0;

/* para ficar mais claro */
#define N_THREADS 4
int n_duplas = N_THREADS/2;

int vez[N_THREADS/2] = { 0, 0 };
int vez_final = 0;

int inter_elim[N_THREADS] = { 0, 0, 0, 0};
int inter_final[N_THREADS] = { 0, 0 };

void* start_thread(void *v) {
  int i;
  int id = *(int *) v;
  int minha_dupla = id / 2;
  
  for (i = 0; i < 120; i++) 
    {

      inter_elim[id] = 1;
      vez[minha_dupla] = id;
      while (vez[minha_dupla] == id && inter_elim[id+1]) ; 

      sleep(1);
      inter_final[minha_dupla] = 1;
      vez_final = id;
      while (vez_final == id && inter_final[(minha_dupla + 1) % n_duplas]) ; 

      sleep(1);
      s = id;
      printf("Thread %d, s = %d.\n", id, s); 

      inter_final[minha_dupla] = 0;
      inter_elim[id] = 0;
    }
  
  return NULL;
}


int main() {

  pthread_t thr0, thr1, thr2, thr3;
  int t_id[4] = { 0, 1, 2, 3 };

  pthread_create(&thr0, NULL, start_thread, &t_id[0]);
  pthread_create(&thr1, NULL, start_thread, &t_id[1]);
  pthread_create(&thr2, NULL, start_thread, &t_id[2]);
  pthread_create(&thr3, NULL, start_thread, &t_id[3]);

  pthread_join(thr0, NULL); 
  pthread_join(thr1, NULL); 
  pthread_join(thr2, NULL); 
  pthread_join(thr3, NULL); 

  return 0;
}


/* author: Gustavo Sverzut Barbieri (http://www.gustavobarbieri.com.br) */

