Simple producer/consumer queue

Preamble
A very simple example of a single producer/consumer using locks and move operations.

Code
[js]
template
class ProdCon
{
public:
void push(T&& w_)
{
scoped_lock lock{_mtx};
if (_q.empty())
{
_cv.notify_one();
}
_q.emplace(move(w_));
}

T pop()
{
unique_lock lock{_mtx};
_cv.wait(lock, [this](){ return !_q.empty(); } );
auto& w = _q.front();
_q.pop();
return move(w);
}
private:
queue _q;
mutex _mtx;
condition_variable _cv;
};
[/js]

Points to note are:

  • Objects of type T are only ever moved.
  • The queue is only signalled when it is empty for efficiency reasons.
  • Full code
    [js]
    #include
    #include
    #include
    #include #include
    using namespace std;

    template
    class ProdCon
    {
    public:
    void push(T&& w_)
    {
    scoped_lock lock{_mtx};
    if (_q.empty())
    {
    _cv.notify_one();
    }
    _q.emplace(move(w_));
    }

    T pop()
    {
    unique_lock lock{_mtx};
    _cv.wait(lock, [this](){ return !_q.empty(); } );
    auto& w = _q.front();
    _q.pop();
    return move(w);
    }
    private:
    queue _q;
    mutex _mtx;
    condition_variable _cv;
    };

    //——————-TestCode———————–

    static int widgetNum = 1;

    class Widget
    {
    public:
    Widget() : _widgetNum{widgetNum++} {}
    Widget(const Widget&) = delete;
    Widget& operator=(const Widget&) = delete;
    Widget(Widget&&) = default;
    Widget& operator=(Widget&&) = default;

    int num() { return _widgetNum; }

    private:
    int _widgetNum;
    };

    void staticTest()
    {
    cout << "staticTest" << endl; widgetNum = 1; Widget w1, w2, w3, w4; ProdCon pc;

    pc.push(move(w1));
    pc.push(move(w2));

    cout << pc.pop().num() << endl; cout << pc.pop().num() << endl; pc.push(move(w3)); cout << pc.pop().num() << endl; pc.push(move(w4)); cout << pc.pop().num() << endl; } void dynamicTest() { cout << "dynamicTest" << endl; widgetNum = 1; Widget w1, w2, w3, w4; ProdCon pc;

    auto prod = [&](){ pc.push(move(w1)); pc.push(move(w2)); pc.push(move(w3)); pc.push(move(w4)); };
    auto con = [&](){ for(int i = 1; i<=4; ++i) {cout << pc.pop().num() << endl;}; }; auto fut = async(launch::async, con); async(launch::async, prod); //wait for consumer fut.get(); } int main() { staticTest(); dynamicTest(); return 0; } [/js]

    Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.