00001 00017 #ifndef THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 00018 #define THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 00019 00020 00021 #include "locking_ptr.hpp" 00022 00023 #include <boost/smart_ptr.hpp> 00024 #include <boost/optional.hpp> 00025 #include <boost/thread/mutex.hpp> 00026 #include <boost/thread/condition.hpp> 00027 #include <boost/thread/xtime.hpp> 00028 #include <boost/utility/result_of.hpp> 00029 #include <boost/static_assert.hpp> 00030 #include <boost/type_traits.hpp> 00031 00032 namespace boost { namespace threadpool { namespace detail 00033 { 00034 00035 template<class Result> 00036 class future_impl 00037 { 00038 public: 00039 typedef Result const & result_type; 00040 00041 typedef Result future_result_type; 00042 typedef future_impl<future_result_type> future_type; 00043 00044 private: 00045 volatile bool m_ready; 00046 volatile future_result_type m_result; 00047 00048 mutable mutex m_monitor; 00049 mutable condition m_condition_ready; 00050 00051 volatile bool m_is_cancelled; 00052 volatile bool m_executing; 00053 00054 public: 00055 00056 00057 public: 00058 00059 future_impl() 00060 : m_ready(false) 00061 , m_is_cancelled(false) 00062 { 00063 } 00064 00065 bool ready() const volatile 00066 { 00067 return m_ready; 00068 } 00069 00070 void wait() const volatile 00071 { 00072 const future_type* self = const_cast<const future_type*>(this); 00073 mutex::scoped_lock lock(self->m_monitor); 00074 00075 while(!m_ready) 00076 { 00077 self->m_condition_ready.wait(lock); 00078 } 00079 } 00080 00081 00082 bool timed_wait(boost::xtime const & timestamp) const 00083 { 00084 const future_type* self = const_cast<const future_type*>(this); 00085 mutex::scoped_lock lock(self->m_monitor); 00086 00087 while(!m_ready) 00088 { 00089 if(!self->m_condition_ready.timed_wait(lock, timestamp)) return false; 00090 } 00091 00092 return true; 00093 } 00094 00095 00096 result_type operator()() const volatile 00097 { 00098 wait(); 00099 /* 00100 if( throw_exception_ != 0 ) 00101 { 00102 throw_exception_( this ); 00103 } 00104 */ 00105 00106 return *(const_cast<const future_result_type*>(&m_result)); 00107 } 00108 00109 00110 void set_value(future_result_type const & r) volatile 00111 { 00112 locking_ptr<future_type, mutex> lockedThis(*this, m_monitor); 00113 if(!m_ready && !m_is_cancelled) 00114 { 00115 lockedThis->m_result = r; 00116 lockedThis->m_ready = true; 00117 lockedThis->m_condition_ready.notify_all(); 00118 } 00119 } 00120 /* 00121 template<class E> void set_exception() // throw() 00122 { 00123 m_impl->template set_exception<E>(); 00124 } 00125 00126 template<class E> void set_exception( char const * what ) // throw() 00127 { 00128 m_impl->template set_exception<E>( what ); 00129 } 00130 */ 00131 00132 00133 bool cancel() volatile 00134 { 00135 if(!m_ready || m_executing) 00136 { 00137 m_is_cancelled = true; 00138 return true; 00139 } 00140 else 00141 { 00142 return false; 00143 } 00144 } 00145 00146 00147 bool is_cancelled() const volatile 00148 { 00149 return m_is_cancelled; 00150 } 00151 00152 00153 void set_execution_status(bool executing) volatile 00154 { 00155 m_executing = executing; 00156 } 00157 }; 00158 00159 00160 template< 00161 template <typename> class Future, 00162 typename Function 00163 > 00164 class future_impl_task_func 00165 { 00166 00167 public: 00168 typedef void result_type; 00169 00170 typedef Function function_type; 00171 typedef typename result_of<function_type()>::type future_result_type; 00172 typedef Future<future_result_type> future_type; 00173 00174 // The task is required to be a nullary function. 00175 BOOST_STATIC_ASSERT(function_traits<function_type()>::arity == 0); 00176 00177 // The task function's result type is required not to be void. 00178 BOOST_STATIC_ASSERT(!is_void<future_result_type>::value); 00179 00180 private: 00181 function_type m_function; 00182 shared_ptr<future_type> m_future; 00183 00184 public: 00185 future_impl_task_func(function_type const & function, shared_ptr<future_type> const & future) 00186 : m_function(function) 00187 , m_future(future) 00188 { 00189 } 00190 00191 void operator()() 00192 { 00193 if(m_function) 00194 { 00195 m_future->set_execution_status(true); 00196 if(!m_future->is_cancelled()) 00197 { 00198 // TODO future exeception handling 00199 m_future->set_value(m_function()); 00200 } 00201 m_future->set_execution_status(false); // TODO consider exceptions 00202 } 00203 } 00204 00205 }; 00206 00207 00208 00209 00210 00211 } } } // namespace boost::threadpool::detail 00212 00213 #endif // THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED 00214 00215