In the following class a worker thread is started within constructor. The worker has a blocking call to a queue.
It works as expected, but when the AsyncQueue
object gets out of scope (for whatever reason), its destructor is called. Also, the destructor of the simple_queue object is called (what I checked by debugging).
But what happens to the worker? Because it is still waiting on the blocking call to the queue!
I observed, that without calling impl_thread_.detach();
within the destructor execution crashes.
However, I don't know whether this is a solution at all. What I don't understand additionally: although the queue object is destroyed the blocking call is not raising an exception - in fact I set a break-point in the catch handler. So what is going on here and what is the right way to implement that scenario? I deeply feel, that what I do here is not quite as it should be ;-)
template<typename T>
class AsyncQueue
{
public:
AsyncQueue() : impl_thread_(&AsyncQueue::worker, this)
{
tq_ = std::shared_ptr<simple_queue<T>>(new simple_queue<T>);
impl_thread_.detach();
}
//~AsyncQueue() = default;
~AsyncQueue() {
std::cout << "[" << boost::this_thread::get_id() << "] destructor AsyncQueue" << std::endl;
return;
}
private:
std::thread impl_thread_;
std::shared_ptr<simple_queue<T>> tq_;
void worker()
{
try {
while (true)
{
boost::optional<T> item = tq_->deq(); // blocks
...
...
...
}
}
catch (exception const& e) {
return;
}
}
public:
...
...
};