Originally Posted by
tabstop
I assume you mean the buffer variable that's global. You'll have to define what you mean by "output is all messed up". I assume that you intend your buffer to be a number of 128-byte chunks, and that each consumer takes a chunk? Depending on luck, I suppose you might get the chunks out of order depending on how you're divvying up the work.
Well it won't store any of my file contents into the buffer, and right now, I'm have problems all together with my output.
NOTE: The while loops in the consumer and producer functions isn't formatted correctly, sorry if there's confusion
Code:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#define FILESIZE 19
#define BUFFER_SIZE 5
#define PRODUCERS 20
#define CONSUMERS 20
struct fifo_struct
{
char fileName[1024];
struct fifo_struct* next;
};
struct linked_list
{
struct fifo_struct* head;
struct fifo_struct* tail;
};
pthread_mutex_t mutex;
sem_t full, empty;
char buffer[BUFFER_SIZE][128];
int counter;
void print_queue(const struct linked_list* ps)
{
struct fifo_struct* p = NULL;
if(ps)
{
for(p = ps->head; p; p = p->next)
{
if(p)
printf("int = %s\n", p->fileName);
else
printf("can't print NULL STRUCT\n");
}
}
}
void *producer(void *q);
void *consumer(void *q);
int main()
{
pthread_t producerVar[PRODUCERS];
pthread_t consumerVar[CONSUMERS];
char line[1024];
char str[200];
int i = 0;
counter = 0;
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_mutex_init(&mutex,NULL);
struct fifo_struct* fifo;
struct linked_list* s = malloc( 1 * sizeof(*s));
if(s == NULL)
{
fprintf(stderr, "LINE: %d, malloc() failed\n", __LINE__);
}
s->head = s->tail = NULL;
for(i = 0; i < (FILESIZE + 1); i++)
{
sprintf(str, "in%d.txt", i);
fifo = malloc(1 * sizeof(*fifo));
if(fifo == NULL)
{
fprintf(stderr, "IN %s, %s: malloc() failed\n", __FILE__, "list_add");
}
strcpy(fifo->fileName,str);
fifo->next = NULL;
if(s == NULL)
{
printf("Error: Queue has not been initialized\n");
}
else if(s->head == NULL && s->tail == NULL)
{
s->head = s->tail = fifo;
}
else if(s->head == NULL || s->tail == NULL)
{
printf("Error: Problem with code\n");
free(fifo);
}
else
{
s->tail->next = fifo;
s->tail = fifo;
}
}
//print_queue(s);
for(i = 0; i < 20; i++)
{
pthread_create(&producerVar[i], NULL, producer, s);
//pthread_join(producerVar, NULL);
}
for(i = 0; i < 5; i++)
{
pthread_create(&consumerVar[i], NULL, consumer, s);
//pthread_join(consumerVar, NULL);
}
return 0;
}
void *producer(void *arg)
{
int i = 0;
char fileContent[1024];
char line[1024];
FILE * myfile;
struct linked_list *q = arg;
printf("IN PRODUCER\n");
//print_queue(q);
struct fifo_struct* tmp1 = NULL;
struct fifo_struct* tmp2 = NULL;
while(1)
{
sem_wait(&empty);
pthread_mutex_lock(&mutex);
if(q == NULL)
{
printf("List is empty\n");
return(NULL);
}
else if(q->head == NULL && q->tail == NULL)
{
printf("List is empty\n");
return(NULL);
}
else if(q->head == NULL || q->tail == NULL)
{
printf("Error: Problem with code\n");
return(NULL);
}
myfile = fopen(q->head->fileName,"r+");
while ((fgets(line, 1024, myfile)) != NULL)
{
strcpy(fileContent, line);
printf("%s",fileContent);
}
fclose(myfile);
while(fileContent[i] != '\n')
{
fileContent[i] = toupper(fileContent[i]);
i++;
}
//printf("%s\n", fileContent);
if(counter < BUFFER_SIZE)
{
strncpy(buffer[counter],fileContent,128);
printf("buffer[%d] = %c\n", counter, buffer[counter]);
counter++;
}
//strncpy(buffer[0],fileContent,128);
//printf("%s\n", fileContent);
tmp1 = q->head;
tmp2 = tmp1->next;
free(tmp1);
q->head = tmp2;
if(q->head == NULL)
q->tail = q->head;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
//print_queue(q);
return(NULL);
}
void *consumer(void *q)
{
int i = 0;
printf("IN CONSUMER\n");
while(1)
{
sem_wait(&full);
pthread_mutex_lock(&mutex);
if(counter > 0)
{
printf("\t\tbuffer[%d] = %c\n", counter, buffer[counter]);
counter--;
}
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
return(NULL);
}
Each file name just has a let of the alphabet repeated like 5-10 times. Output should look like the following (and the consumer output should vary):
IN PRODUCER
aaaaaaaaa
IN PRODUCER
bbbbbbbbb
IN PRODUCER
ccccccccccc
IN PRODUCER
ddddddd
IN PRODUCER
eeeeeeee
IN PRODUCER
ffffffffff
IN PRODUCER
gggggggg
IN PRODUCER
hhhhhhhh
IN PRODUCER
iiiiiiiiiiiii
IN PRODUCER
jjjjjjjjjj
IN PRODUCER
kkkkkkkkkk
IN PRODUCER
llllllllllllllll
IN PRODUCER
mmmmmm
IN PRODUCER
nnnnnnnnn
IN PRODUCER
ooooooooo
IN PRODUCER
pppppppp
IN PRODUCER
qqqqqqqq
IN PRODUCER
rrrrrrrrr
IN PRODUCER
sssssss
IN PRODUCER
ttttttttt
IN CONSUMER
IN CONSUMER
IN CONSUMER
IN CONSUMER
IN CONSUMER
However, I'm getting something crazy like:
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
aaaaaaaaaa
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN PRODUCER
IN CONSUMER
IN CONSUMER
IN CONSUMER
IN CONSUMER
IN CONSUMER