Producer consumer with threads and using boost ring buffer I have two threads, one is the producer and other is consumer. My consumer is always late (due to some costly function call, simulated in below code using sleeps) so I have used ring buffer as I can afford to loose some events.  

I am looking to see if my locking looks alright and general c++ review comments. 

#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;chrono&gt;
#include &lt;vector&gt;
#include &lt;atomic&gt;
#include &lt;boost/circular_buffer.hpp&gt;
#include &lt;condition_variable&gt;
#include &lt;functional&gt;

std::atomic&lt;bool&gt; mRunning;
std::mutex m_mutex;
std::condition_variable m_condVar;

class VecBuf {
    private:
    std::vector&lt;int8_t&gt; vec;

    public:
    VecBuf() = default;
    VecBuf(std::vector&lt;int8_t&gt; v)
    {
        vec = v;
    }
};

std::vector&lt;int8_t&gt; data{ 10, 20, 30 };

class Detacher {
    public:
    template&lt;typename Function, typename ... Args&gt;
    void createTask(Function &amp;&amp;func, Args&amp;&amp; ... args) {
        m_threads.emplace_back(std::forward&lt;Function&gt;(func), std::forward&lt;Args&gt;(args)...);
    }

    Detacher() = default;
    Detacher(const Detacher&amp;) = delete;
    Detacher &amp; operator=(const Detacher&amp;) = delete;
    Detacher(Detacher&amp;&amp;) = default;
    Detacher&amp; operator=(Detacher&amp;&amp;) = default;

    ~Detacher() {
        for (auto&amp; thread : m_threads) {
            thread.join();
        }
    }

    private:
    std::vector&lt;std::thread&gt; m_threads;
};

void foo_1(boost::circular_buffer&lt;VecBuf&gt; *cb)
{
    while (mRunning) {
        std::unique_lock&lt;std::mutex&gt; mlock(m_mutex);

        m_condVar.wait(mlock, [=]() { return !cb-&gt;empty(); });

        VecBuf local_data(cb-&gt;front());
        cb-&gt;pop_front();
        mlock.unlock();
        if (!mRunning) {
            break;
        }
        //simulate time consuming function call and consume local_data here
        std::this_thread::sleep_for(std::chrono::milliseconds(16));
    }

    while (cb-&gt;size()) {
        VecBuf local_data(cb-&gt;front());
        cb-&gt;pop_front();
        if (!mRunning) {
            break;
        }
    }
}

void foo_2(boost::circular_buffer&lt;VecBuf&gt; *cb)
{
    while (mRunning) {
        std::unique_lock&lt;std::mutex&gt; mlock(m_mutex);

        while (cb-&gt;full()) {
            mlock.unlock();
            /* can we do better than this? */
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            mlock.lock();
        }
        cb-&gt;push_back(VecBuf(data));
        m_condVar.notify_one();
    }
}

int main()
{
    mRunning = true;
    boost::circular_buffer&lt;VecBuf&gt; cb(100);
    Detacher thread_1;
    thread_1.createTask(foo_1, &amp;cb);
    Detacher thread_2;
    thread_2.createTask(foo_2, &amp;cb);
    std::this_thread::sleep_for(std::chrono::milliseconds(20000));
    mRunning = false;
}
/* can we do better than this? */



In a circular buffer context, the standard way to avoid busy waiting is to have two semaphores. First to block a producer when a buffer is full, and second to block a consumer when the buffer is empty. Once a process passes its semaphore, and does its job, it should signal the peer.



The circular buffer is good when the consumer is only sometimes late and you cannot afford loosing data. In your situation it looks like a wrong solution: the producer becomes throttled by the rate of consumption, and the consumer is a presented with the stale data.

A typical answer is to let the producer run at full speed, and triple-buffer the production (at least, it guarantees that the consumer would get the most recently produced data). Please forgive the shameless self promotion.