namespace messaging { class close_queue { }; class dispatcher { queue* q; bool chained; dispatcher(dispatcher const&) = delete; dispatcher& operator=(dispatcher const&) = delete; template friend class TemplateDispatcher; void wait_and_dispatch() { for (;;) { auto msg = q->wait_and_pop(); dispatch(msg); } } bool dispatch(std::shared_ptr const& msg) { if (dynamic_cast*>(msg.get())) { throw close_queue(); } return false; } public: dispatcher(dispatcher&& other) : q(other.q), chained(other.chained) { other.chained = true; } explicit dispatcher(queue* q_) : q(q_), chained(false) {} template TemplateDispatcher handle(Func&& f) { return TemplateDispatcher( q, this, std::forward(f)); } ~dispatcher() noexcept(false) { if (!chained) { wait_and_dispatch(); } } }; } // namespace messaging