I have some code which I adapted (barely changing it) from the C++ Concurrency In Action book, so would have expected it to work -- only it doesn't. What I've tried to do is to implement a thread-safe queue that I can then store background jobs for a thread or threads in. The queue looks like this:

Code:
/* imgproc/queue.h */

#pragma once
#include "imgproc/i_queue.h"
#include <memory>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>

using namespace std;

namespace imgproc {

  /* Blocking, concurrency-safe queue. The method that blocks is pop(),
   * which makes the current thread wait until there is a value to pop
   * from the queue.
   */
  template <typename T>
    struct ConcurrentQueue : public IQueueWriter<T>, public IQueueReader<T>
    {
      ConcurrentQueue() {}
      ConcurrentQueue( const ConcurrentQueue & ) = delete;
      ConcurrentQueue & operator= ( const ConcurrentQueue & ) = delete;

      /* Concurrency-safe push to queue.
       */
      virtual void push( shared_ptr<T> val )
      {
        lock_guard<mutex> lk( _mutex );
        _queue.push( val );
        _cvar.notify_one();
      }

      /* Concurrency-safe check if queue empty.
       */
      virtual const bool empty() const
      {
        lock_guard<mutex> lk( _mutex );
        bool result( _queue.empty() );
        return result;
      }

      /* Waiting, concurrency-safe pop of value. If there are no values in
       * the queue, then this method blocks the current thread until there
       * are.
       */
      virtual shared_ptr<T> pop()
      {
        unique_lock<mutex> lk( _mutex );
        _cvar.wait( lk, [ this ] {return ! _queue.empty(); } );
        auto value( _queue.front() );
        _queue.pop();
        return value;
      }

    private:
      mutable mutex _mutex;
      queue<shared_ptr<T>> _queue;
      condition_variable _cvar;
    };

}
My understanding is that the one mutex there should protect all attempts to access the queue. However, I have a test that crashes about 1 time in 10:

Code:
/* test-that-crashes-fragment.cpp */
// Should have threads wait until there is a value to pop
TEST_F( ConcurrentQueueTest,
        ShouldHaveThreadsWaitUntilThereIsAValueToPop ) {
  int val( -1 );
  thread t1( [ this, &val ] {
      for ( uint i( 0 ) ; i < 1000 ; ++i );
      val = *_r_queue->pop();
    } );
  for ( uint i( 0 ) ; i < 1000 ; ++ i ) {
    for ( uint j( 0 ) ; j < 1000 ; ++ j );
    EXPECT_EQ( -1, val );
  }
  _w_queue->push( make_shared<int>( 27 ) );
  t1.join();
  EXPECT_EQ( 27, val );
  EXPECT_TRUE( _r_queue->empty() );
}
The variables _r_queue and _w_queue are just interfaces on the same ConcurrentQueue instance, here.

From hours spent obsessively cout-ing debug info, it looks like the call to pop() is what causes the crash, always (that I've seen) when the _queue member instance variable is empty. Could anyone offer me any advice as to what I'm doing wrong, here? I've seen other posts asking for help with similar problems, but they always seem to say that conditional variables are the answer -- and I'm trying that!

Or maybe some advice on how I can debug this better to help me solve it? FWIW, I tried manually implementing a while with a sleep( 1 ) in it, and that still periodically crashed, which rather suggests I've managed to get a race condition despite my best efforts -- only I really can't see it.

Thanks very much for any & all help, and I promise I've tried to figure this out before bothering you all with it.

Cheers, Doug.