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., 59 Temple Place - Suite 330, Boston, MA 00016 * 02111-1307, USA. 00017 */ 00018 00019 #ifndef __ASYNC_WORKER__ 00020 #define __ASYNC_WORKER__ 00021 00022 #include <asio.hpp> 00023 #include <boost/bind.hpp> 00024 #include <boost/function.hpp> 00025 #include <boost/noncopyable.hpp> 00026 #include <boost/enable_shared_from_this.hpp> 00027 #include "ut_debugmsg.h" 00028 #include <sync/xp/Synchronizer.h> 00029 00030 template <class T> 00031 class AsyncWorker : private boost::noncopyable, public boost::enable_shared_from_this<AsyncWorker<T> > 00032 { 00033 public: 00034 AsyncWorker(boost::function<T ()> async_func, boost::function<void (T)> async_callback) 00035 : m_async_func(async_func), 00036 m_async_callback(async_callback), 00037 m_synchronizer() // can't initialize the synchronizer here yet, because you can't call shared_from_this() from a constructor 00038 { 00039 } 00040 00041 virtual ~AsyncWorker() 00042 { 00043 UT_DEBUGMSG(("~AsyncWorker()\n")); 00044 if (m_thread_ptr) 00045 m_thread_ptr->join(); 00046 } 00047 00048 virtual void start() 00049 { 00050 m_synchronizer.reset(new Synchronizer(boost::bind(&AsyncWorker<T>::_signal, 00051 boost::enable_shared_from_this<AsyncWorker<T> >::shared_from_this()))); 00052 m_thread_ptr.reset( 00053 new asio::thread( 00054 boost::bind(&AsyncWorker::_thread_func, 00055 AsyncWorker<T>::shared_from_this()) 00056 ) 00057 ); 00058 } 00059 00060 private: 00061 void _signal() 00062 { 00063 UT_DEBUGMSG(("Calling async callback function from the main loop\n")); 00064 m_async_callback(m_func_result); 00065 } 00066 00067 void _thread_func() 00068 { 00069 UT_DEBUGMSG(("Starting async function...\n")); 00070 m_func_result = m_async_func(); 00071 UT_DEBUGMSG(("Async function completed...\n")); 00072 m_synchronizer->signal(); 00073 } 00074 00075 boost::function<T ()> m_async_func; 00076 boost::function<void (T)> m_async_callback; 00077 boost::shared_ptr<Synchronizer> m_synchronizer; 00078 boost::shared_ptr<asio::thread> m_thread_ptr; 00079 T m_func_result; 00080 }; 00081 00082 #endif /* __ASYNC_WORKER__ */