C++ fixed-size queue full/empty signaling I'm considering an application where a large data needs to be written to file often.  I would like to use a queue and have a producer and consumer running on different threads.  Additionally, I would like to have a fixed size queue as the data size can be very large.  I've implemented a simple test of boost::lockfree::queue with boost::condition_variable to signal the state of the queue.  I would like to avoid the mutex but for the exception where the queue is full (block producer) or empty (block consumer)

I would like to know (at risk of opinion based..) if I'm using conditionals properly or if there is a performance issue - compared to using other methods.  Here is what I've done so far (small data)

#include &lt;iostream&gt;
#include &lt;boost/thread/thread.hpp&gt;
#include &lt;boost/lockfree/queue.hpp&gt;

#define N 6
#define QN 3   

struct testdata {
    int a;
    int b;
};

boost::lockfree::queue&lt;testdata, boost::lockfree::fixed_size&lt;true&gt;&gt; que(QN);
boost::condition_variable que_has_data, que_has_room;
boost::mutex que_mtx_hd, que_mtx_hr;

void producer(void) {
    testdata td;
    int i = 0;
    boost::mutex::scoped_lock lock(que_mtx_hr);
    boost::this_thread::sleep(boost::posix_time::seconds(1));
    for (;;) {
        td.a = i; td.b = i + 1;
        if (!que.push(td)) {
            std::cout &lt;&lt; "producer waiting" &lt;&lt; std::endl;
            que_has_room.wait(lock);
        } else {
            std::cout &lt;&lt; "pushed " &lt;&lt; td.a &lt;&lt; std::endl;
            i += 1;
            que.has_data_notify_one();
        }
        if (i &gt; N)
            break;
    }
}

void consumer(void) {
    testdata td;
    boost::mutex::scoped_lock lock(que_mtx_hd);
    for (;;) {
        if (que.pop(td)) {
            std::cout &lt;&lt; "popped " &lt;&lt; td.a &lt;&lt; std::endl;
            if (td.a == N)
                break;
            que_has_room.notify_one();
        } else {
           std::cout &lt;&lt; "consumer waiting" &lt;&lt; std::endl;
           que_has_data.wait(lock);
        }
    }
    boost::this_thread::sleep(boost::posix_time::seconds(1));
}

int main(void) {
    boost::thread t1(&amp;producer);
    boost::thread t2(&amp;consumer);
    t1.join();
    t2.join();
    return 0;
}


This works (output):

consumer waiting
pushed 0
pushed 1
pushed 2
producer waiting
popped 0
pushed 3
producer waiting
popped 1
pushed 4
producer waiting
popped 2
pushed 5
producer waiting
popped 3
pushed 6
popped 4
popped 5
popped 6


I anticipate that for the most part, data will almost always be available but I want to block in the case of congestion (file write, network, etc).  The interest in fixed size is the worry of massive data sets and dynamic allocation in the queue - 

(This is more an experiment in what can be done.  In reality, my data is updated at most about 20 Hz so just taking a lock on a std::queue that I manage the size of will work very well, too.)
Use a semaphore to cause the producers to sleep when the queue is full, and another semaphore to cause the consumers to sleep when the queue is empty.
when the queue is neither full nor empty, the sem_post and sem_wait operations are nonblocking (in newer kernels)

#include &lt;semaphore.h&gt;

template&lt;typename lock_free_container&gt;
class blocking_lock_free
{
public:
    lock_free_queue_semaphore(size_t n) : container(n)
    {
        sem_init(&amp;pop_semaphore, 0, 0);
        sem_init(&amp;push_semaphore, 0, n);
    }

    ~lock_free_queue_semaphore()
    {
        sem_destroy(&amp;pop_semaphore);
        sem_destroy(&amp;push_semaphore);
    }

    bool push(const lock_free_container::value_type&amp; v)
    {
        sem_wait(&amp;push_semaphore);
        bool ret = container::bounded_push(v);
        ASSERT(ret);
        if (ret)
            sem_post(&amp;pop_semaphore);
        else
            sem_post(&amp;push_semaphore); // shouldn't happen
        return ret;
    }

    bool pop(lock_free_container::value_type&amp; v)
    {
        sem_wait(&amp;pop_semaphore);
        bool ret = container::pop(v);
        ASSERT(ret);
        if (ret)
            sem_post(&amp;push_semaphore);
        else
            sem_post(&amp;pop_semaphore); // shouldn't happen
        return ret;
    }
private:
    lock_free_container container;
    sem_t pop_semaphore;
    sem_t push_semaphore;
};