я писал недавно как-то так
while(true) {
std::function<void ()> action;
{unique_lock<mutex> lk(mx);
cv.wait(lk, []{ return !msq_queue.empty() || job_finished; });
if (job_finished) break;
action = std::move(msg_queue.front());
msg_queue.pop_back();
}
action();
}