
Christopher Kohlhoff wrote:
--- Vaclav Vesely <vaclav.vesely@email.cz> wrote: ...
I've written ASIO background_thread class which calls arbitrary functions in a background thread. If you find it useful, you can add it to examples. After some refining it may be even added to the ASIO library. ... Actually I think there may be a way to simplify your code here - assuming I correctly understand what you're trying to do.
The code seems to use the data members m_has_work and m_has_work_condition to keep restarting the demuxer::run() function whenever it has new work to do. The worker thread waits on the condition if the demuxer doesn't have any work to do. ... Not exactly. The worker thread stops when there is no work to do and async_run it's again if it's not running.
However I think now, that your solution with a work thread permanently running is better. The reworked example is attached. Regards, Vaclav #include <iostream> #include "boost/asio.hpp" #include "boost/bind.hpp" #include "boost/date_time/posix_time/posix_time.hpp" #include "boost/thread.hpp" //----------------------------------------------------------------------------- template<typename Demuxer> class async_object { public: typedef Demuxer demuxer_type; public: async_object(demuxer_type& demuxer): m_demuxer(demuxer) { } demuxer_type& demuxer() { return m_demuxer; } protected: demuxer_type& m_demuxer; }; //----------------------------------------------------------------------------- template<typename Demuxer> class background_worker: public async_object<Demuxer> { public: background_worker(Demuxer& demuxer): async_object(demuxer), m_work_demuxer(), m_dummy_work(new boost::asio::demuxer::work(m_work_demuxer)) { } ~background_worker() { m_dummy_work.reset(); if(m_work_thread) m_work_thread->join(); } private: template<typename Function, typename Handler> class run_proc { public: run_proc(demuxer_type& demuxer, Function function, Handler handler): m_demuxer(demuxer), m_work(demuxer), m_function(function), m_handler(handler) { } void operator()() { m_function(); m_demuxer.post(m_handler); } private: demuxer_type& m_demuxer; typename demuxer_type::work m_work; Function m_function; Handler m_handler; }; public: template<typename Function, typename Handler> void async_run(Function function, Handler handler) { m_work_demuxer.post(run_proc<Function, Handler>(m_demuxer, function, handler)); if(!m_work_thread) { m_work_thread.reset(new boost::thread(boost::bind( &background_worker::work_thread_proc, this))); } } private: void work_thread_proc() { m_work_demuxer.run(); } private: boost::asio::demuxer m_work_demuxer; boost::scoped_ptr<boost::thread> m_work_thread; boost::scoped_ptr<boost::asio::demuxer::work> m_dummy_work; }; //----------------------------------------------------------------------------- boost::mutex cout_mutex; void wait(int seconds) { { boost::mutex::scoped_lock lock(cout_mutex); std::cout << "Wait for " << seconds << " seconds" << std::endl; } boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); xt.sec += seconds; boost::thread::sleep(xt); } void wait_finished() { { boost::mutex::scoped_lock lock(cout_mutex); std::cout << "Waiting finished." << std::endl; } } //----------------------------------------------------------------------------- void main() { boost::asio::demuxer demuxer; background_worker<boost::asio::demuxer> bg_thread(demuxer); bg_thread.async_run(boost::bind(wait, 1), wait_finished); bg_thread.async_run(boost::bind(wait, 1), wait_finished); demuxer.run(); bg_thread.async_run(boost::bind(wait, 1), wait_finished); demuxer.reset(); demuxer.run(); } //-----------------------------------------------------------------------------