#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define TAM_BUFFER 5

pthread_mutex_t s = PTHREAD_MUTEX_INITIALIZER;
sem_t cn;
sem_t pr;
int buffer[TAM_BUFFER];

void *productor(void *arg) {
  int n = *((int *)arg);

  for (int i = 0; i < n; i++) {
    sem_wait(&pr);
    pthread_mutex_lock(&s);
    buffer[i % TAM_BUFFER] = rand() % 11;
    printf("Colocado en la posicion %d el valor %d \n", i % TAM_BUFFER,buffer[i % TAM_BUFFER]);
    pthread_mutex_unlock(&s);
    sem_post(&cn);
  }
}

void *consumidor(void *arg) {
  int n = *((int *)arg);

  for (int i = 0; i < n; i++) {
    sem_wait(&cn);
    pthread_mutex_lock(&s);
    printf("Extraida la posicion %d. Valor %d \n", i % TAM_BUFFER,
           buffer[i % TAM_BUFFER]);
    pthread_mutex_unlock(&s);
    sem_post(&pr);
  }
}

int main(int argc, char **argv) {
  int num = atoi(argv[1]);
  if ((argc != 2) || (num < 5)) {
    fprintf(stderr, "Uso: %s <N> (o n mayor que 5)\n ", argv[0]);
    exit(EXIT_FAILURE);
  }

  pthread_t th1, th2;
  int error;
  srand(time(NULL));

  error = sem_init(&cn, 0, 0);
  if (error != 0) {
    printf("sem_init cn error...\n");
  }

  error = sem_init(&pr, 0, TAM_BUFFER);
  if (error != 0) {
    printf("sem_init pr error...\n");
  }

  // CREATES
  error = pthread_create(&th1, NULL, (void *)consumidor, (void *)&num);
  if (error != 0) {
    printf("pthread_create cn error...\n");
    exit(EXIT_FAILURE);
  }

  error = pthread_create(&th2, NULL, (void *)productor, (void *)&num);
  if (error != 0) {
    printf("pthread_create pr error...\n");
    exit(EXIT_FAILURE);
  }

  // JOINS
  error = pthread_join(th1, NULL);
  if (error != 0) {
    printf("pthread_join cn error...\n");
    exit(EXIT_FAILURE);
  }

  error = pthread_join(th2, NULL);
  if (error != 0) {
    printf("pthread_join pr error...\n");
    exit(EXIT_FAILURE);
  }
}
