Bytemaster's Boost Libraries
|
00001 #ifndef BOOST_CMT_TASK_HPP 00002 #define BOOST_CMT_TASK_HPP 00003 #include <boost/enable_shared_from_this.hpp> 00004 #include <boost/cmt/error.hpp> 00005 #include <boost/cmt/retainable.hpp> 00006 #include <boost/cmt/future.hpp> 00007 #include <boost/function.hpp> 00008 #include <boost/exception/diagnostic_information.hpp> 00009 #include <boost/cmt/log/log.hpp> 00010 00011 namespace boost { namespace cmt { 00012 struct priority { 00013 explicit priority( int v = 0):value(v){} 00014 priority( const priority& p ):value(p.value){} 00015 bool operator < ( const priority& p )const { 00016 return value < p.value; 00017 } 00018 int value; 00019 }; 00020 class task : public retainable { 00021 public: 00022 typedef task* ptr; 00023 task(priority p=priority()) 00024 :prio(p),next(0){ 00025 static int64_t global_task_count=0; 00026 posted_num = ++global_task_count; 00027 } 00028 00029 virtual void run() = 0; 00030 virtual void cancel() = 0; 00031 virtual const char* name() { return "unknown"; } 00032 protected: 00033 static int64_t task_num; 00034 friend class thread; 00035 friend class thread_private; 00036 uint64_t posted_num; 00037 priority prio; 00038 task* next; 00039 }; 00040 00041 template<typename R = void> 00042 class rtask : public task { 00043 public: 00044 rtask( const boost::function<R()>& f, const typename promise<R>::ptr& p, priority prio, const char* name = "" ) 00045 :task(prio),m_functor(f),m_prom(p),m_name(name){} 00046 00047 void cancel() { 00048 try { 00049 BOOST_THROW_EXCEPTION( error::task_canceled() ); 00050 } catch ( ... ) { 00051 m_prom->set_exception(boost::current_exception()); 00052 } 00053 } 00054 void run() { 00055 try { 00056 m_prom->set_value( m_functor() ); 00057 } catch( ... ) { 00058 m_prom->set_exception(boost::current_exception()); 00059 } 00060 } 00061 const char* name() { return m_name; } 00062 00063 boost::function<R()> m_functor; 00064 typename promise<R>::ptr m_prom; 00065 const char* m_name; 00066 }; 00067 00068 template<> 00069 class rtask<void> : public task { 00070 public: 00071 rtask( const boost::function<void()>& f, const promise<void>::ptr& p, priority prio=priority(), const char* name = "" ) 00072 :task(prio),m_functor(f),m_prom(p),m_name(name){} 00073 00074 void cancel() { 00075 try { 00076 BOOST_THROW_EXCEPTION( error::task_canceled() ); 00077 } catch ( ... ) { 00078 m_prom->set_exception(boost::current_exception()); 00079 } 00080 } 00081 void run() { 00082 try { 00083 m_functor(); 00084 m_prom->set_value( void_t() ); 00085 } catch( ... ) { 00086 m_prom->set_exception(boost::current_exception()); 00087 } 00088 } 00089 const char* name() { return m_name; } 00090 00091 boost::function<void()> m_functor; 00092 promise<void>:: ptr m_prom; 00093 const char* m_name; 00094 00095 }; 00096 00097 template<typename R = void_t> 00098 class reftask : public task { 00099 public: 00100 reftask( const boost::function<R()>& f, const typename promise<R>::ptr& p, priority prio =priority(), const char* name = "" ) 00101 :task(prio),m_functor(f),m_prom(p),m_name(name){} 00102 00103 void cancel() { 00104 try { 00105 BOOST_THROW_EXCEPTION( error::task_canceled() ); 00106 } catch ( ... ) { 00107 m_prom->set_exception(boost::current_exception()); 00108 } 00109 } 00110 void run() { 00111 try { 00112 m_prom->set_value( m_functor() ); 00113 } catch( ... ) { 00114 m_prom->set_exception(boost::current_exception()); 00115 } 00116 } 00117 const char* name() { return m_name; } 00118 00119 const char* m_name; 00120 const boost::function<R()>& m_functor; 00121 typename promise<R>::ptr m_prom; 00122 }; 00123 template<> 00124 class reftask<void> : public task { 00125 reftask( const boost::function<void()>& f, const promise<void>::ptr& p, priority prio=priority(),const char* name = "" ) 00126 :task(prio),m_functor(f),m_prom(p),m_name(name){} 00127 00128 void cancel() { 00129 try { 00130 BOOST_THROW_EXCEPTION( error::task_canceled() ); 00131 } catch ( ... ) { 00132 m_prom->set_exception(boost::current_exception()); 00133 } 00134 } 00135 void run() { 00136 try { 00137 m_functor(); 00138 m_prom->set_value( void_t()); 00139 } catch( ... ) { 00140 m_prom->set_exception(boost::current_exception()); 00141 } 00142 } 00143 const char* name() { return m_name; } 00144 00145 const boost::function<void()>& m_functor; 00146 promise<void>::ptr m_prom; 00147 const char* m_name; 00148 }; 00149 00150 00151 class vtask : public task { 00152 00153 public: 00154 vtask( const boost::function<void()>& f, priority prio = priority() ) 00155 :task(prio),m_functor(f){ 00156 } 00157 00158 void cancel() {} 00159 void run() { 00160 try { 00161 m_functor(); 00162 } catch( const boost::exception& e ) { 00163 elog( "%1%", boost::diagnostic_information(e) ); 00164 } catch( const std::exception& e ) { 00165 elog( "%1%", boost::diagnostic_information(e) ); 00166 } catch( ... ) { 00167 BOOST_ASSERT(!"unhandled exception"); 00168 } 00169 } 00170 boost::function<void()> m_functor; 00171 }; 00172 00173 } } // namespace boost cmt 00174 00175 #endif // BOOST_CMT_TASK_HPP