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