|
Boost : |
From: Vaclav Vesely (vaclav.vesely_at_[hidden])
Date: 2006-03-24 03:19:25
Christopher Kohlhoff wrote:
> --- Vaclav Vesely <vaclav.vesely_at_[hidden]> 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();
}
//-----------------------------------------------------------------------------
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk