00001 /* Copyright (C) 2008 AbiSource Corporation B.V. 00002 * 00003 * This program is free software; you can redistribute it and/or 00004 * modify it under the terms of the GNU General Public License 00005 * as published by the Free Software Foundation; either version 2 00006 * of the License, or (at your option) any later version. 00007 * 00008 * This program is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 * GNU General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program; if not, write to the Free Software 00015 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00016 * 02110-1301 USA. 00017 */ 00018 00019 #ifndef __ASYNC_WORKER__ 00020 #define __ASYNC_WORKER__ 00021 00022 #if defined(HAVE_BOOST_ASIO_HPP) 00023 # include <boost/asio.hpp> 00024 #else 00025 # include <asio.hpp> 00026 #endif 00027 00028 #include <boost/bind.hpp> 00029 #include <boost/function.hpp> 00030 #include <boost/noncopyable.hpp> 00031 #include <boost/enable_shared_from_this.hpp> 00032 #include "ut_debugmsg.h" 00033 #include <sync/xp/Synchronizer.h> 00034 00035 template <class T> 00036 class AsyncWorker : private boost::noncopyable, public boost::enable_shared_from_this<AsyncWorker<T> > 00037 { 00038 public: 00039 AsyncWorker(boost::function<T ()> async_func, boost::function<void (T)> async_callback) 00040 : m_async_func(async_func), 00041 m_async_callback(async_callback), 00042 m_synchronizer() // can't initialize the synchronizer here yet, because you can't call shared_from_this() from a constructor 00043 { 00044 } 00045 00046 virtual ~AsyncWorker() 00047 { 00048 UT_DEBUGMSG(("~AsyncWorker()\n")); 00049 if (m_thread_ptr) 00050 m_thread_ptr->join(); 00051 } 00052 00053 virtual void start() 00054 { 00055 m_synchronizer.reset(new Synchronizer(boost::bind(&AsyncWorker<T>::_signal, 00056 boost::enable_shared_from_this<AsyncWorker<T> >::shared_from_this()))); 00057 m_thread_ptr.reset( 00058 new asio::thread( 00059 boost::bind(&AsyncWorker::_thread_func, 00060 AsyncWorker<T>::shared_from_this()) 00061 ) 00062 ); 00063 } 00064 00065 private: 00066 void _signal() 00067 { 00068 UT_DEBUGMSG(("Calling async callback function from the main loop\n")); 00069 m_async_callback(m_func_result); 00070 } 00071 00072 void _thread_func() 00073 { 00074 UT_DEBUGMSG(("Starting async function...\n")); 00075 m_func_result = m_async_func(); 00076 UT_DEBUGMSG(("Async function completed...\n")); 00077 m_synchronizer->signal(); 00078 } 00079 00080 boost::function<T ()> m_async_func; 00081 boost::function<void (T)> m_async_callback; 00082 boost::shared_ptr<Synchronizer> m_synchronizer; 00083 boost::shared_ptr<asio::thread> m_thread_ptr; 00084 T m_func_result; 00085 }; 00086 00087 #endif /* __ASYNC_WORKER__ */