/*
 * Ceci est du code *GruiK* no copyright is allowed !
 */

#include <pthread.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <semaphore.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>


#define NUMTHREADS 10
#define TRUE  1
#define FALSE 0
void sighand(int signo);
#define pthread_id_np_t unsigned long
sem_t sem; /* semaphore object */

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  cond = PTHREAD_COND_INITIALIZER;
int counter = 1;



void *threadfunc1(void *parm)
{
   struct timespec ts;
   struct timeval  tp;
   int rc;
   int lock=FALSE;

   gettimeofday(&tp,NULL);
   ts.tv_sec = tp.tv_sec + 5 ;
   ts.tv_nsec = tp.tv_usec * 1000;

   pthread_mutex_lock(&mutex);
   if(counter <=  0) {
     rc = pthread_cond_timedwait(&cond,&mutex,&ts);
     
     if(rc == 0)
     {
       lock = TRUE;
       counter --;
     }
     else
     {
       if(rc == ETIMEDOUT)
       {
         printf("TH%05d @ %05d : TIMEOUT\n",pthread_self(),time(NULL));
       }
     }
   }
   else {
       lock = TRUE;
       counter --;
   }

   pthread_mutex_unlock(&mutex);
   
   if(! lock) {
     pthread_exit(NULL);
   } 

   printf("TH%05d @ %05d : ->in lock \n",pthread_self(),time(NULL));


   sleep(1);

   pthread_mutex_lock(&mutex);
   counter++;
   printf("TH%05d @ %05d : <- out lock \n",pthread_self(),time(NULL));
   pthread_mutex_unlock(&mutex);
   pthread_cond_signal(&cond);

   pthread_exit(NULL);

}


int main(int argc, char **argv)
{
  int                     rc;
  int                     i;
  struct sigaction        actions;
  pthread_t               threads[NUMTHREADS];


  pthread_mutex_init(&mutex,NULL);
  pthread_cond_init(&cond, NULL);


  for(i=0; i<NUMTHREADS; ++i) {
    rc = pthread_create(&threads[i], NULL, threadfunc1, NULL);
  }
  
  for(i=0; i<NUMTHREADS; ++i) {
    pthread_join(threads[i], NULL);
  }

  pthread_mutex_lock(&mutex);
  pthread_mutex_unlock(&mutex);
  pthread_cond_destroy(&cond);
  pthread_mutex_destroy(&mutex);
  printf("Main completed\n");
  return 0; 

}