Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6792125
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T17:55:49+00:00 2026-05-26T17:55:49+00:00

I am trying to solve a consumer/producer problem, and I have to create three

  • 0

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!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T17:55:50+00:00Added an answer on May 26, 2026 at 5:55 pm

    See also:

    • Should I use #include in headers?
    • What are extern variables in C?

    ringbuf.h

    Your ringbuf.h header should be self-contained and idempotent. It should, therefore, include <pthread.h>.

    #ifndef RINGBUF_H_INCLUDED
    #define RINGBUF_H_INCLUDED
    
    #include <pthread.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 */
    };
    
    /* 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);
    
    #endif /* RINGBUF_H_INCLUDED */
    

    Were it my header, I’d have an extra line:

    typedef struct ringbuf_t ringbuf_t;
    

    and I’d edit the function prototypes to lose the struct keyword.

    The advantage of this is that anyone can include ringbuf.h and it will simply work for them.

    ringbuf.c

    It is crucial that the implementation file uses its own header; that gives you the necessary cross-checking that the header accurately reflects what is implemented. It should also be the first header included; this gives a simple but effective check that the header is self-contained.

    You should not use <malloc.h> unless you are using its extended features. The <stdlib.h> declares malloc() et al and should be used unless you know which extra functions are available in <malloc.h> and you actually use them.

    This leads to:

    #include "ringbuf.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    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");
        }
    }
    

    You should probably use fprintf(stderr, ...) rather than printf() for diagnostics, and you should consider how to turn them off at run-time (or, more likely, how to turn them on).

    Note that it is conventional to put system-provided headers in angle brackets (hence <stdio.h>) and user-provided headers in double quotes (hence "ringbuf.h").

    Your rb_init() function should initialize the structure completely. That means that the mutex and the two condition variables should both be initialized properly. It also needs to either initialize (zero) the buf member or allocate the appropriate amount of space – more likely the latter. Your code should check that the allocations succeed, and only use the allocated space if it does.

    You should also review whether it is appropriate to make the producer and consumer threads manipulate the mutex and condition variables. If they are bundled with the structure, the functions bundled with the structure should do what is necessary with the mutexes and conditions. This would allow you to simplify the producer and consumer to just call the ring buffer functions. Clearly, the main() will still launch the two threads, but if you get your abstraction right, the threads themselves won’t need to dink with mutexes and conditions directly; the ring buffer library code will do that correctly for the threads. One of the advantages of this is that your library can get the operations right, once, and all consumers benefit. The alternative is to have every producer and consumer handle the mutexes and conditions – which magnifies the opportunities to get it wrong. In a classroom situation where you won’t use the abstraction again after this exercise, the proper separation and encapsulation is not so critical, but in professional code, it is crucial that the library make it easy for people to use the code correctly and hard for them to make mistakes.

    main.c

    In C, you cannot initialize a global variable with a function call – in C++, you can.

    Hence, this won’t compile in C:

    //creating a static ring buffer
    struct ringbuf_t *mybuffer = rb_init(10);
    

    You should use:

    struct ringbuf_t *mybuffer = 0;
    

    and then, in main() or a function called from main() – directly or indirectly – do the function call:

    mybuffer = rb_init(10);
    

    This would be before you do any work creating the threads. When your rb_init() code initializes the mutex and condition variables, your main() will be able to go ahead as written.

    Until then, you have a good deal of cleanup to do.


    Disclaimer I have not compiled the code to see what the compiler witters about.

    Note If you use GCC but don’t compile with at least -Wall and preferably -Wextra too (and clean up any (all) the warnings), you are missing out on a very important assistant. I work with retrograde code bases where I have to worry about -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes too. Using -Werror can be helpful; it forces you to clean up the warnings.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have been trying to solve this problem for three days now, it's really
Trying to solve a problem with templatetags. I have two templatetags: @register.inclusion_tag('directory/_alphabet.html') def alphabet_list(names):
I am trying to solve this problem. I have a series of SELECT statements
Trying to solve a problem of preventing duplicate images to be uploaded. I have
I'm trying to solve the following problem: I have a download button that when
Trying to solve this problem: I have the following set of divs that when
I'm trying to solve this problem where I have a unique array of values
In trying to solve the ajax back button problem I have found the Really
I'm trying to solve the 3n+1 problem and I have a for loop that
Trying to solve that problem, but no luck for hours... I have var screen1

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.