I was watching Herb Sutter's talk at the C++ and Beyond 2012 conference on Concurrency and he talks about creating a non-blocking wrapper class, which he calls concurrent<T>
, with C++11 functions.
His implementation is fairly simple (aside from needing a concurrent_queue
such as that which exists in Microsoft's PPL):
template <class T>
class concurrent {
private:
mutable T t;
mutable concurrent_queue<std::function<void()>> q;
bool done = false;
std::thread thread;
public:
concurrent( T t_ = T{} ) : t{t_}, thread{ [=]{ while( !done ) q.pop()(); }} {}
~concurrent() { q.push( [=]{ done = true; } ); thread.join(); }
template <typename F>
void operator()( F f ) const { q.push( [=]{ f(t); } ); }
};
This seems simple enough, however, I'm confused as to why he has captured the member variables done
and q
by value instead of by reference? My understanding is that if they are captured by value then they will be copied to the thread and thus when the queue is updated the worker thread will not receive the updates?
Have I misunderstood how lambda captures work with regards to class member variables? No one said anything in the comments to the video or during the talk so I am assuming that my understanding is faulty, in which case could someone please clarify?
Member variables can never be captured by value. What's being captured by value is the implicit
this
pointer used to access them. Therefore, it's capturing a pointer by value, which means it captures this object (and its members) by reference.