00001 #ifndef _BOOST_CMT_FUTURE_HPP
00002 #define _BOOST_CMT_FUTURE_HPP
00003 #include <boost/cmt/retainable.hpp>
00004 #include <boost/cmt/error.hpp>
00005 #include <boost/thread/mutex.hpp>
00006 #include <boost/cmt/mutex.hpp>
00007 #include <boost/optional.hpp>
00008
00009 namespace boost { namespace cmt {
00010
00011 class abstract_thread;
00012 class promise_base : public retainable {
00013 public:
00014 typedef retainable_ptr<promise_base> ptr;
00015 promise_base():m_blocked_thread(0),m_timeout(-1){}
00016 virtual ~promise_base(){}
00017
00018 virtual bool ready()const = 0;
00019 protected:
00020 void enqueue_thread();
00021 void wait( uint64_t timeout_us );
00022 void notify();
00023 virtual void set_timeout()=0;
00024 virtual void set_exception( const boost::exception_ptr& e )=0;
00025
00026 private:
00027 friend class thread;
00028 friend class thread_private;
00029
00030 abstract_thread* m_blocked_thread;
00031 uint64_t m_timeout;
00032 };
00033
00034 struct void_t {};
00035
00036 template<typename T = void_t>
00037 class promise : public promise_base {
00038 public:
00039 typedef retainable_ptr<promise> ptr;
00040
00041 promise(){}
00042 promise( const T& v ):m_value(v){}
00043
00044 bool ready()const {
00045 boost::unique_lock<mutex> lock( m_mutex );
00046 return !!m_value || m_error;
00047 }
00048 operator const T&()const { return wait(); }
00049
00050 const T& wait(uint64_t timeout = -1) {
00051 {
00052 boost::unique_lock<mutex> lock( m_mutex );
00053 if( m_error ) boost::rethrow_exception(m_error);
00054 if( m_value ) return *m_value;
00055 enqueue_thread();
00056 }
00057 promise_base::wait(timeout);
00058 if( m_error ) boost::rethrow_exception(m_error);
00059 if( m_value ) return *m_value;
00060 BOOST_THROW_EXCEPTION( error::future_value_not_ready() );
00061 return *m_value;
00062 }
00063 void set_exception( const boost::exception_ptr& e ) {
00064 {
00065 boost::unique_lock<mutex> lock( m_mutex );
00066 m_error = e;
00067 }
00068 notify();
00069 }
00070 void set_value( const T& v ) {
00071 {
00072 boost::unique_lock<mutex> lock( m_mutex );
00073 if( m_error )
00074 return;
00075 m_value = v;
00076 }
00077 notify();
00078 }
00079
00080 private:
00081 void set_timeout() {
00082 {
00083 boost::unique_lock<mutex> lock( m_mutex );
00084 if( m_value )
00085 return;
00086 m_error = boost::copy_exception( error::future_wait_timeout() );
00087 }
00088 notify();
00089 }
00090
00091 mutable mutex m_mutex;
00092 boost::exception_ptr m_error;
00093 boost::optional<T> m_value;
00094 };
00095
00096 template<>
00097 class promise<void> : public promise<void_t> {};
00098
00121 template<typename T = void_t>
00122 class future {
00123 public:
00124 typedef typename promise<T>::ptr promise_ptr;
00125
00126 future( const promise_ptr& p = promise_ptr() )
00127 :m_prom(p){}
00128
00129 bool valid()const { return !!m_prom; }
00130 bool ready()const { return m_prom->ready(); }
00131 operator const T&()const {
00132 if( !m_prom ) BOOST_THROW_EXCEPTION( error::null_future() );
00133 return m_prom->wait();
00134 }
00135 const T& wait(uint64_t timeout = -1) {
00136 if( !m_prom ) BOOST_THROW_EXCEPTION( error::null_future() );
00137 return m_prom->wait(timeout);
00138 }
00139
00140 private:
00141 promise_ptr m_prom;
00142 };
00143
00144 template<>
00145 class future<void> : public future<void_t> {
00146 public:
00147 future( const promise<void_t>::ptr& p = promise<void_t>::ptr() )
00148 :future<void_t>(p){}
00149 };
00150
00151
00152 } }
00153
00154
00155 #endif