http://informatica.uv.es/iiguia/SO/lab/prac4/

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <pthread.h>

#include "buffer.h"

int TAM=1024;

/***
*** Datos compartidos
***/
/* buffer compartido por productores y consumidores */
buffer_t *b;

/* mutex para exclusion mutua */
pthread_mutex_t mtx;

/* variable condicion para que esperen los productores */
pthread_cond_t cond_prod;

/* variable condicion para que esperen los consumidores */
pthread_cond_t cond_cons;

/* indicador para que los consumidores sepan que no quedan productores y
* que, por lo tanto, cuando el buffer se vacia deben terminar
* (no deben terminar inmediatamente, porque entonces podrian quedarse
* sin tratar las ltimas lineas depositadas por los productores) */
int terminar = 0;



/***
*** Funciones base de los hilos
***/
/*
* funcion base de los productores
* - cada productor copia linea a linea un fichero en el buffer compartido
* - el argumento es el puntero al nombre del fichero del que leer
*/
void *productor(void *arg)
{
    printf ("Productor %lu fichero de entrada %s\n", pthread_self(),(char *)arg);
    FILE *f;
    int fin;
    char linea[TAM];


    f = fopen((char *)arg,"r");

    if (f == NULL)
    {
        perror("Error del sistema");
        printf("No se puede abrir \"%s\" para leer\n\n",(char *)arg);
            exit(1);
    }
    while (!fin)
    {
            if(fgets(linea,TAM,f) != NULL)
            {

                pthread_mutex_lock(&mtx); // Obtener acceso exlusivo al buffer
                while (buf_lleno(b)) // espero mientras en buffer eet lleno
                {
                    pthread_cond_wait(&cond_prod, &mtx);
                }

                buf_poner(b,strdup(linea)); //Insertar linea en el buffer
                pthread_cond_signal(&cond_cons);
                pthread_mutex_unlock(&mtx);
            }else
                fin =1;
    }
    fclose(f);
    pthread_exit(0);
    return 0;
}




/*
* funcion base de los consumidores
* - cada consumidor va volcando linea a linea el contenido del buffer
*  en el fichero cuyo nombre se le pasa como parametro
*/
void *consumidor(void *arg)

{
    char *linea;
    FILE *f_out;

    printf ("Consumidor%lu fichero de salida %s\n", pthread_self(),(char *)arg);

    f_out = fopen((char *)arg,"w");

    while (!buf_vacio(b) || terminar!=1) //Mientras el buffer este lleno o terminar este a 0
    {
        pthread_mutex_lock(&mtx);//El acceso es exclusivo
        while (buf_vacio(b) && terminar!=1)
        {
            pthread_cond_wait(&cond_cons,&mtx);//Si el buffer esta vacio que no lea
          }

        if(buf_vacio(b))
        {
            terminar = 1;
            pthread_mutex_unlock(&mtx);//Desbloquea el acceso exclusivo
        }else
        {


            linea = buf_quitar(b);

            pthread_cond_signal(&cond_prod);//Avisa al productor por si quiere escribir
            pthread_mutex_unlock(&mtx);

              printf("Consumir : %s ",linea);
            fprintf(f_out,"%s",linea);
            free(linea);
        }
    }
        fclose(f_out);

    return NULL;
}



/***
*** Programa principal

***/
/*
* funcion para indicar como utilizar el programa
*/
static void uso(const char *prog)
{
    fprintf(stderr,
            "Uso: %s fich_de_salida fich_de_entrada_1 [f2 [...]]\n",
            prog);
    exit(1);
}

/*
* funcion base del hilo principal del programa
*/
int main(int argc, char *argv[])
{
  int i;
  int argum =argc-2;
  pthread_t p[argum];

  if (argc < 3 ) // si no tiene tres parametros se ejecuta uso/user1/Desktop/hilos.html#fichero-main-c
  {
    uso(argv[0]);
  }
  b = buf_crear(TAM);

  pthread_mutex_init(&mtx,NULL);
  pthread_cond_init(&cond_prod,NULL);
  pthread_cond_init(&cond_cons,NULL);

  for(i=0;i<argum;i++)
  {
    pthread_create(&p[i],NULL,productor,argv[i+2]);

  }
  pthread_create(&p[0],NULL,consumidor,argv[1]);

  for (i = 1; i < argum; ++i)
  {
        pthread_join(p[i], NULL);
  }

  pthread_mutex_lock(&mtx);

  terminar = 1;
  pthread_cond_signal(&cond_cons);

  pthread_mutex_unlock(&mtx);

  pthread_join(p[0], NULL);




  pthread_cond_destroy(&cond_prod);
  pthread_cond_destroy(&cond_cons);
  buf_imprimir(b);




  return 0;
}