I am trying to solve a consumer/producer problem, and I have to create three different classes.
The main class includes the creation of threads, and consumer/producer logic
the other two classes are
- A header file for a ring buffer
- A file containing the implementation of the ring buffer
I'm getting the following errors when trying to compile:
ringbuf.c: In function ‘rb_init’:
ringbuf.c:10: warning: incompatible implicit declaration of built-in function ‘malloc’
ringbuf.c:10: error: invalid application of ‘sizeof’ to incomplete type ‘struct ringbuf_t’
ringbuf.c:12: error: dereferencing pointer to incomplete type
I many other errors, but I can handle them myself once I get through this one.
this is the header file for the buffer:
struct ringbuf_t
{
pthread_mutex_t mutex; /* lock to protect from simutaneous access to the buffer */
pthread_cond_t cond_full; /* producer needs to wait when the buffer is full */
pthread_cond_t cond_empty; /* consumer needs to wait when the buffer is empty */
int bufsiz; /* size of the buffer; you may use an empty slot to differentiate the situation the buffer is full or empty */
int front; /* index of the first element */
int back; /* index next to the last element (or index to the first empty slot) */
int count; //keeps track of the number of elements in the buffer
char* buf; /* buffer itself */
};
/* return the pointer to the newl created and initialized ring buffer of the given size */
extern struct ringbuf_t* rb_init(int bufsiz);
/* reclaim the ring buffer */
extern void rb_finalize(struct ringbuf_t* rb);
/* return the current number of elements in the buffer */
extern int rb_size(struct ringbuf_t* rb);
/* return non-zero (true) if the buffer is currently full */
extern int rb_is_full(struct ringbuf_t* rb);
/* return non-zero (true) if the buffer is currently empty */
extern int rb_is_empty(struct ringbuf_t* rb);
/* insert (i.e., append) a character into the buffer; if the buffer is full, the caller thread will be blocked */
extern void rb_insert(struct ringbuf_t* rb, int c);
/* retrieve a character at the front of the ring buffer; if the buffer is empty, the caller thread will be blocked */
extern int rb_remove(struct ringbuf_t* rb);
and this is the implementation of the buffer:
#include <malloc.h>
#include <stdio.h>
struct ringbuf_t
{
pthread_mutex_t mutex; /* lock to protect from simutaneous access to the buffer */
pthread_cond_t cond_full; /* producer needs to wait when the buffer is full */
pthread_cond_t cond_empty; /* consumer needs to wait when the buffer is empty */
int bufsiz; /* size of the buffer; you may use an empty slot to differentiate the situation the buffer is full or empty */
int front; /* index of the first element */
int back; /* index next to the last element (or index to the first empty slot) */
int count; //keeps track of the number of elements in the buffer
char* buf; /* buffer itself */
};
struct ringbuf_t* rb_init(int bufsiz)
{
struct ringbuf_t* buffer = (struct ringbuf_t*)malloc(sizeof(struct ringbuf_t));
buffer->bufsiz = bufsiz;
buffer->front = 0;
buffer->back = 0;
buffer->count = 0;
}
/* reclaim the ring buffer */
void rb_finalize(struct ringbuf_t* rb)
{
free(rb);
pthread_mutex_destroy(&rb->mutex);
printf("\nnotice - ring buffer finalized");
}
/* return the current number of elements in the buffer */
int rb_size(struct ringbuf_t* rb)
{
return (rb->count);
}
/* return non-zero (true) if the buffer is currently full */
int rb_is_full(struct ringbuf_t* rb)
{
return ((rb->count) == rb->bufsiz);
}
/* return non-zero (true) if the buffer is currently empty */
int rb_is_empty(struct ringbuf_t* rb)
{
return ((rb->count) == 0);
}
/* insert (i.e., append) a character into the buffer; if the buffer is full, the caller thread will be blocked */
void rb_insert(struct ringbuf_t* rb, int c)
{
char* temp;
if(rb->count < rb->bufsiz)
{
if(rb->count == 0)
{
rb->front = 0;
rb->back = 0;
rb->buf = c;
rb->count++;
}
else
{
if(rb->front < (rb->bufsiz - 1))
{
temp = rb->buf;
temp = temp + rb->front + 1;
temp = c;
rb->front++;
}
else if(rb->front == (rb->bufsiz -1))
{
rb->front = 0;
rb->buf = c;
}
}
}
else
{
printf("\nerror - trying to insert into full buffer");
}
}
/* retrieve a character at the tail (back) of the ring buffer; if the buffer is empty, the caller thread will be blocked */
int rb_remove(struct ringbuf_t* rb)
{
if(rb->count != 0)
{
count--;
if(rb->back < (rb->bufsiz-1)
{
rb->back++;
}
else if(rb->back == (rb->bufsiz -1))
{
rb->back = 0;
}
}
else
{
printf("\nerror - trying to remove from empty buffer");
}
}
this is the main class:
#include <stdio.h>
#include <pthread.h>
#include <ringbuf.h>
//creating a static ring buffer
struct ringbuf* mybuffer = rb_init(10);
int thisChar;
/*
consumer thread, reads one character at a time, sets the lock when addinga character to the ring buffer
while locked it checks if the buffer is full, waits for a slot, and then continues.
*/
void* consumer(void* arg)
{
printf("consumer started");
while(thisChar != EOF)
{
pthread_mutex_lock(&(mybuffer->mutex));
while(rb_is_empty(mybuffer))
pthread_cond_wait(&(mybuffer->cond_full), &(mybuffer->mutex));
printf("%s", (char)rb_remove(mybuffer));
pthread_cond_signal(&(mybuffer->cond_empty));
pthread_mutex_unlock(&(mybuffer->mutex));
}
}
/*
producer thread, takes one character at a time from the buffer, (while the buffer is not empty)
and prints it to the screen.
*/
void* producer(void* arg)
{
printf("producer started");
while ((thisChar = getchar()) != EOF)
{
pthread_mutex_lock(&(mybuffer->mutex));
while(rb_is_full(mybuffer))
pthread_cond_wait(&(mybuffer->cond_empty), &(mybuffer->mutex));
rb_insert(mybuffer, thisChar);
pthread_cond_signal(&(mybuffer->cond_full));
pthread_mutex_unlock(&(mybuffer->mutex));
}
}
int main()
{
//declaring threads
pthread_t t0, t1;
//creating threads as condumer, producer
p_thread_create(&t0, NULL, consumer, (void*)mybuffer);
p_thread_create(&t1, NULL, producer, (void*)mybuffer);
pthread_join(t0, NULL);
pthread_join(t1, NULL);
rb_finalize(mybuffer);
return 0;
}
I'm missing some stuff, but I need to get through this first! please help!