Buffer Limitato
Jump to navigation
Jump to search
Esercizio di programmazione concorrente:
Il programma genera 2 thread.
Il primo di questi, detto producer, prende i valori da stdin e li scrive su un buffer.
Il secondo, detto consumer, legge i valori dal buffer e li scrive su un file.
Requisiti:
- Il buffer è usato come array circolare
- Producer non deve scrivere su valori non ancora letti
- Consumer deve leggere i valori in ordine e senza ripetizioni
Soluzione di MV, usando i semafori
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DIM_BUF 10
#define THREAD_SHARED 0
char buffer[DIM_BUF];
int next_write = 0, next_read = 0; // indici sul buffer
sem_t empty; // semaforo: consumer si blocca su di esso quando il buffer è vuoto
sem_t full; // semaforo: producer si blocca su di esso quando il buffer è pieno
void* producer_routine(void *arg)
{
char c;
while(scanf("%c",&c) != EOF) // legge ("produce") un carattere da stdin
{
if(sem_wait(&full) != 0) // si blocca se il buffer è pieno
{
printf("Error %i in producer: %s",errno,strerror(errno));
break;
}
buffer[next_write] = c;
next_write = (next_write+1)%DIM_BUF;
if(sem_post(&empty) != 0) // segnala un nuovo carattere non letto sul buffer
{
printf("Error %i in producer: %s",errno,strerror(errno));
break;
}
}
}
void* consumer_routine(void * arg)
{
FILE *file;
if( (file = fopen("./consumed.txt","a")) == NULL)
{
printf("Error %i in consumer: %s",errno,strerror(errno));
return NULL;
}
while(1)
{
char c;
if(sem_wait(&empty) != 0) // se il buffer è vuoto si blocca
{
printf("Error %i in consumer: %s",errno,strerror(errno));
break;
}
fprintf(file,"%c",buffer[next_read]);
next_read = (next_read+1)%DIM_BUF;
if(sem_post(&full) != 0) // segnala che si è liberato un posto sul buffer
{
printf("Error %i in consumer: %s",errno,strerror(errno));
break;
}
}
close(file);
}
int main(int argc, char* argv[])
{
pthread_t producer, consumer;
int *error, i;
for(i=0; i< DIM_BUF; i++)
buffer[i] = 0;
if(sem_init(&empty,THREAD_SHARED,0) != 0) // inizializzato a 0 perchè il buffer è vuoto
return errno;
if(sem_init(&full,THREAD_SHARED,DIM_BUF) != 0) // servono DIM_BUF scritture per riempirlo
return errno;
pthread_create(&producer,NULL,&producer_routine,NULL);
pthread_create(&consumer,NULL,&consumer_routine,NULL);
pthread_join(producer, (void**)&error); // aspetta la terminazione di producer
printf("End.\n");
return 0;
}