#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h> // Para la función sleep()

// Declaramos un semáforo global
sem_t semaforo;

// Función que ejecutará cada hilo
void* acceder_recurso(void* arg) {
    // Obtenemos el ID del hilo
    int id = *((int*)arg);
    
    printf("Hilo %d intentando acceder al recurso...\n", id);
    
    // Operación WAIT (o P): Toma un "lugar" o se bloquea si el contador llega a 0
    sem_wait(&semaforo);
    
    // --- INICIO DE SECCIÓN CRÍTICA ---
    printf("-> Hilo %d ENTRO a la seccion critica.\n", id);
    sleep(2); // Simulamos trabajo usando el recurso durante 2 segundos
    printf("<- Hilo %d SALIO de la seccion critica.\n", id);
    // --- FIN DE SECCIÓN CRÍTICA ---
    
    // Operación SIGNAL (o V): Libera el "lugar" sumando 1 al contador
    sem_post(&semaforo);
    
    return NULL;
}

int main() {
    pthread_t hilos[5];
    int ids[5] = {1, 2, 3, 4, 5};
    
    // Inicializamos el semáforo:
    // Primer parámetro: puntero al semáforo
    // Segundo parámetro: 0 significa que se comparte entre hilos del mismo proceso
    // Tercer parámetro: valor inicial (2 lugares disponibles)
    if (sem_init(&semaforo, 0, 2) != 0) {
        perror("Error al inicializar el semaforo");
        return 1;
    }
    
    printf("Iniciando 5 hilos, pero el semaforo solo permite 2 a la vez.\n\n");
    
    // Creamos los 5 hilos
    for (int i = 0; i < 5; i++) {
        pthread_create(&hilos[i], NULL, acceder_recurso, &ids[i]);
    }
    
    // El hilo principal (main) espera a que todos los hilos terminen (join)
    for (int i = 0; i < 5; i++) {
        pthread_join(hilos[i], NULL);
    }
    
    // Destruimos el semáforo para liberar la memoria del sistema operativo
    sem_destroy(&semaforo);
    
    printf("\nTodos los hilos han terminado. Programa finalizado.\n");
    return 0;
}