0

I'm trying to do this simple program, where I want to use the take and append functions, which access a buffer implemented with a list, in a producer-consumer problem:

#ifndef buf_h
#define buf_h

#include <list>
using std::list;
#include <mutex>
using std::mutex;
#include <condition_variable>
using std::condition_variable;

class Buffer
{
    public:
        Buffer(int cap);
        void append(int shift);
        int take();
        
    private:
        list<double> Buffer_;
        int capacity_;

        int count_;
          
        mutex mutex_;
        condition_variable not_full_;
        condition_variable not_empty_;
};

#endif

This is buffer:

#include "buf.h"

#include <list>
using std::list;
#include <mutex>
using std::mutex;
using std::unique_lock;
#include <condition_variable>
using std::condition_variable;

Buffer::Buffer(int capacity)
    : Buffer_(capacity,0), capacity_{capacity}, count_{0}
{
}

void Buffer::append(int shift) 
{ 
    unique_lock<mutex> mlock(mutex_);
    while(count_== capacity_)
        not_full_.wait(mlock);
    Buffer_.push_back(shift);
    ++count_;
    not_empty_.notify_one();
}

int Buffer::take() 
{
    unique_lock<mutex> mlock(mutex_);
    while(count_ == 0)
        not_empty_.wait(mlock);

    int w = Buffer_.front();
    Buffer_.pop_front();
    --count_;
    not_full_.notify_one();
    return w;
}

This is main:

#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <thread>
using std::thread;

#include "buf.h"


Buffer B1{20};

void producer(int id){
    B1.append(id);
}

void consumer(){
    int w = B1.take();
    cout<< w <<endl;
}

int main()
{
    for(int i=0; i<5; ++i){
        thread prod(producer, i);
        thread cons(consumer);
    prod.join();
        cons.join();
    }

    return 0;
}

I don't understand why if I use push_back() in append, I get all 0 as output, when instead I should get this:

0
1
2
3
4

If I use push_front() the output is correct. Can anyone help me?

1 Answer 1

1

In your constructor:

    Buffer_(capacity,0)

This does not do what you think it does. If you inspect what's in the Buffer_ immediately after construction you will discover that it's not empty, and the resulting program's behavior becomes easy to explain.

TLDR: the initializes the buffer with a whole bunch of values, which are all 0, which completely messes up the logic in the rest of the code which assumes that the buffer is initially empty.

Sign up to request clarification or add additional context in comments.

3 Comments

I think the OP is confused about the term capacity and is not familiar with the C++ term size. You might wish to elaborate on that.
There's no "capacity", of any kind, in a std::list.
But there is a "size".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.