Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to use lambda functions as predicate for condition_variable wait method

I am trying to make the producer-consumer method using c++11 concurrency. The wait method for the condition_variable class has a predicate as second argument, so I thought of using a lambda function:

struct LimitedBuffer {
    int* buffer, size, front, back, count;
    std::mutex lock;
    std::condition_variable not_full;
    std::condition_variable not_empty;

    LimitedBuffer(int size) : size(size), front(0), back(0), count(0) {
        buffer = new int[size];
    }   

    ~LimitedBuffer() {
        delete[] buffer;
    }

    void add(int data) {
        std::unique_lock<std::mutex> l(lock);

        not_full.wait(l, [&count, &size]() {
            return count != size;
        });

        buffer[back] = data;
        back = (back+1)%size;
        ++count;

        not_empty.notify_one();
    }

    int extract() {
        std::unique_lock<std::mutex> l(lock);

        not_empty.wait(l, [&count]() {
            return count != 0;
        });

        int result = buffer[front];
        front = (front+1)%size;
        --count;

        not_full.notify_one();

        return result;
    }
};

But I am getting this error:

[Error] capture of non-variable 'LimitedBuffer::count'

I don't really know much about c++11 and lambda functions so I found out that class members can't be captured by value. By value though, I am capturing them by reference, but it seems like it's the same thing.

In a display of brilliance I stored the struct members values in local variables and used them in the lambda function, and it worked! ... or not:

int ct = count, sz = size;
not_full.wait(l, [&ct, &sz]() {
    return ct != sz;
});

Obviously I was destroying the whole point of the wait function by using local variables since the value is assigned once and the fun part is checking the member variables which may, should and will change. Silly me.

So, what are my choices? Is there any way I can make the wait method do what it has to do, using the member variables? Or I am forced to not use lambda functions so I'd have to declare auxiliary functions to do the work?

I don't really get why I can't use members variables in lambda functions, but since the masters of the universe dessigned lamba functions for c++11 this way, there must be some good reason.

like image 535
dabadaba Avatar asked Nov 05 '25 17:11

dabadaba


1 Answers

count is a member variable. Member variables can not be captured directly. Instead, you can capture this to achieve the same effect:

not_full.wait(l, [this] { return count != size; });
like image 115
nosid Avatar answered Nov 07 '25 15:11

nosid



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!