Per preparami ad un esame di Programmazione concorrente devo risolvere un problema dei produttori consumatori definendo un oggetto buffer_t che mi rappresenta il buffer contenente D indice inserimento buffer circolare, T indice estrazione elementi buffer circolare e un buffer circolare che contiene dei messaggi del tipo msg_t *.
Io ho scritto il seguente codice:
codice:
GestioneBuffer.c
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
#define BUFFERERROR (msg_t *) NULL;
typedef char* stringa;
typedef struct msg {
void* content;
// generico contenuto del messaggio
struct msg * (*msg_init_string)(void*);
// creazione msg
void (*msg_destroy_string)(struct msg *);
// deallocazione msg
struct msg * (*msg_copy_string)(struct msg *); // creazione/copia msg
} msg_t;
typedef struct buffer{
int K; //numero messaggi
int N; //capacita bffer circolare
int D;
int T;
msg_t **buffer_circolare;
pthread_mutex_t mutex;
pthread_cond_t non_pieno;
pthread_cond_t non_vuoto;
}buffer_t;
void msg_destroy_string(msg_t* msg) {
free(msg->content); // free copia privata
free(msg);
// free struct
}
msg_t* msg_copy_string(msg_t* msg) {
return msg->msg_init_string( msg->content );
}
msg_t* msg_init_string(void* content) {
//viene creata una copia "privata" della stringa
msg_t* new_msg = (msg_t*)malloc( sizeof(msg_t) );
char* string = (char*)content;
char* new_content = (char*)malloc(strlen(string)+1); // +1 per \0 finale
strcpy(new_content, string);
new_msg->content=new_content;
new_msg->msg_init_string=msg_init_string;
new_msg->msg_destroy_string=msg_destroy_string;
new_msg->msg_copy_string=msg_copy_string;
return new_msg;
}
void buffer_destroy(buffer_t* buffer){
free(buffer);
}
buffer_t* buffer_init(unsigned int maxsize){
buffer_t *buffer;
buffer = (buffer_t *)malloc(sizeof(buffer_t));
buffer->buffer_circolare = malloc(maxsize*sizeof(msg_t));
buffer->D=0;
buffer->K=0;
buffer->T=0;
buffer->N=maxsize;
pthread_mutex_init(&buffer->mutex,NULL);
pthread_cond_init(&buffer->non_pieno,NULL);
pthread_cond_init(&buffer->non_vuoto,NULL);
return buffer;
}
msg_t* put_non_bloccante(buffer_t *buffer){
pthread_mutex_lock(&buffer->mutex);
if(buffer->K==buffer->N){
printf("Il buffer è pieno e il mutex è rilasciato\n");
pthread_mutex_unlock(&buffer->mutex);
return NULL;
}else{
msg_t* msg=msg_init_string("Messaggio");
buffer->buffer_circolare[buffer->D]=msg_copy_string(msg);
printf("Il produttore inserisce il messaggio\n");
buffer->D=(buffer->D+1)%buffer->N;
buffer->K=buffer->K+1;
pthread_cond_signal(&buffer->non_vuoto);
pthread_mutex_unlock(&buffer->mutex);
return msg;
}
}
msg_t* put_bloccante(buffer_t *buffer){
msg_t *msg = msg_init_string("Messaggio");
pthread_mutex_lock(&buffer->mutex);
while(buffer->K==buffer->N){
printf("Il Produttore è in attesa che il buffer sia vuoto\n");
pthread_cond_wait(&buffer->non_pieno,&buffer->mutex);
}
buffer->buffer_circolare[buffer->D]=msg_copy_string(msg);
printf("Il produttore inserisce il messaggio\n");
buffer->D=(buffer->D+1)%buffer->N;
buffer->K=buffer->K+1;
pthread_cond_signal(&buffer->non_vuoto);
pthread_mutex_unlock(&buffer->mutex);
return msg;
/**}else return BUFFERERROR;*/
}
msg_t* get_bloccante(buffer_t* buffer){
msg_t*result;
pthread_mutex_lock(&buffer->mutex);
while(buffer->K==0){
printf("Il consumatore è in attesa che il buffer venga riempito\n");
pthread_cond_wait(&buffer->non_vuoto,&buffer->mutex);
}
printf("Il consumatore preleva un messaggio\n");
result=(msg_t*)malloc( sizeof(msg_t) );
result=buffer->buffer_circolare[buffer->T];
buffer->buffer_circolare[buffer->T]=NULL;
buffer->T=(buffer->T+1)%buffer->N;
buffer->K=buffer->K-1;
pthread_cond_signal(&buffer->non_pieno);
pthread_mutex_unlock(&buffer->mutex);
return result;
}
msg_t* get_non_bloccante(buffer_t* buffer){
pthread_mutex_lock(&buffer->mutex);
if(buffer->K==0){
printf("Il consumatore non preleva poiche buffer vuoto\n");
pthread_mutex_unlock(&buffer->mutex);
return NULL;
}else{
printf("Il consumatore preleva un messaggio\n");
msg_t* result=(msg_t*)malloc( sizeof(msg_t) );
result=msg_copy_string(buffer->buffer_circolare[buffer->T]);
buffer->buffer_circolare[buffer->T]=NULL;
buffer->T=(buffer->T+1)%buffer->N;
buffer->K=buffer->K-1;
pthread_cond_signal(&buffer->non_pieno);
pthread_mutex_unlock(&buffer->mutex);
return result;
}
}
msg_t* dummy_produttore(buffer_t* buffer){
msg_t *msg = msg_init_string("Messaggio");
pthread_mutex_lock(&buffer->mutex);
buffer->buffer_circolare[buffer->D]=msg_copy_string(msg);
printf("Il produttore inserisce il messaggio\n");
buffer->D=(buffer->D+1)%buffer->N;
buffer->K=buffer->K+1;
pthread_cond_signal(&buffer->non_vuoto);
pthread_mutex_unlock(&buffer->mutex);
return msg;
}
msg_t* dummy_consumatore(buffer_t* buffer){
msg_t*result;
pthread_mutex_lock(&buffer->mutex);
printf("Il consumatore preleva un messaggio\n");
result=(msg_t*)malloc( sizeof(msg_t) );
result=buffer->buffer_circolare[buffer->T];
buffer->buffer_circolare[buffer->T]=NULL;
buffer->T=(buffer->T+1)%buffer->N;
buffer->K=buffer->K-1;
pthread_cond_signal(&buffer->non_pieno);
pthread_mutex_unlock(&buffer->mutex);
return result;
}
Cosi come l'ho scritto funziona ma non rispetta le specifiche dell'homework. Infatti i metodi put e get devono avere come parametri buffer_t* e msg_t*(per intenderci put_bloccante(buffer_t* buffer,msg_t* msg))
Io ho provato a scrivere il metodo put_bloccante in questo modo:
codice:
msg_t* put_bloccante(buffer_t *buffer,msg_t* msg){
msg = msg_init_string("Messaggio");
pthread_mutex_lock(&buffer->mutex);
while(buffer->K==buffer->N){
printf("Il Produttore è in attesa che il buffer sia vuoto\n");
pthread_cond_wait(&buffer->non_pieno,&buffer->mutex);
}
buffer->buffer_circolare[buffer->D]=msg_copy_string(msg);
printf("Il produttore inserisce il messaggio\n");
buffer->D=(buffer->D+1)%buffer->N;
buffer->K=buffer->K+1;
pthread_cond_signal(&buffer->non_vuoto);
pthread_mutex_unlock(&buffer->mutex);
return msg;
/**}else return BUFFERERROR;*/
}
Ma se eseguo tale metodo(invocandolo nel main mediante pthread_create(&th1,NULL,put_bloccante,(buffer_vuo to,msg))) non mi viene visualizzato in output alcun tipo di messaggio.
Volevo sapere se qualcuno mi potesse aiutare nel trovare l'errore