Bytemaster's Boost Libraries
/Users/dlarimer/dev/libs/cmt/include/boost/cmt/future.hpp
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 #include <boost/chrono.hpp>
00009 
00010 namespace boost { namespace cmt {
00011     using boost::chrono::microseconds;
00012 
00013     class abstract_thread;
00014     class promise_base :  public retainable {
00015          public:
00016              typedef retainable_ptr<promise_base> ptr;
00017              promise_base():m_blocked_thread(0),m_timeout(microseconds::max()){}
00018              virtual ~promise_base(){}
00019 
00020              virtual bool ready()const = 0;
00021          protected:
00022              void enqueue_thread();
00023              void wait( const microseconds& timeout_us );
00024              void notify();
00025              virtual void set_timeout()=0;
00026              virtual void set_exception( const boost::exception_ptr& e )=0;
00027 
00028          private:
00029              friend class thread;
00030              friend class thread_private;
00031 
00032              abstract_thread*          m_blocked_thread;
00033              microseconds              m_timeout;    
00034     };
00035 
00036     struct void_t {};
00037 
00038     template<typename T = void_t>
00039     class promise : public promise_base {
00040         public:
00041             typedef retainable_ptr<promise> ptr;
00042 
00043             promise(){}
00044             promise( const T& v ):m_value(v){}
00045 
00046             bool ready()const { 
00047                 boost::unique_lock<mutex> lock( m_mutex );
00048                 return !!m_value || m_error; 
00049             }
00050             bool error()const { return m_error; }
00051             operator const T&()const  { return wait();  }
00052 
00053             const T& wait(const microseconds& timeout = microseconds::max() ) {
00054                 { // lock while we check values
00055                     boost::unique_lock<mutex> lock( m_mutex );
00056                     if( m_error ) boost::rethrow_exception(m_error);
00057                     if( m_value ) return *m_value;
00058                     enqueue_thread();
00059                 } // unlock before yielding, but after enqueing
00060                 promise_base::wait(timeout);
00061                 if( m_error ) boost::rethrow_exception(m_error);
00062                 if( m_value ) return *m_value;
00063                 BOOST_THROW_EXCEPTION( error::future_value_not_ready() ); 
00064                 return *m_value;
00065             }
00066             void set_exception( const boost::exception_ptr& e ) {
00067                 {
00068                     boost::unique_lock<mutex> lock( m_mutex );
00069                     m_error = e;
00070                 }
00071                 notify();
00072             }
00073             void set_value( const T& v ) {
00074                 {
00075                     boost::unique_lock<mutex> lock( m_mutex );
00076                     if( m_error ) 
00077                         return;
00078                     m_value = v;
00079                 }
00080                 notify();
00081             }
00082             
00083         private:
00084             void set_timeout() {
00085                 {
00086                     boost::unique_lock<mutex> lock( m_mutex );
00087                     if( m_value ) 
00088                         return;
00089                     m_error = boost::copy_exception( error::future_wait_timeout() );
00090                 }
00091                 notify();
00092             }
00093 
00094             mutable mutex           m_mutex;
00095             boost::exception_ptr    m_error;
00096             boost::optional<T>      m_value;
00097     };
00098 
00099     template<>
00100     class promise<void> : public promise<void_t> {};
00101 
00124     template<typename T = void_t>
00125     class future {
00126         public:
00127                 typedef typename promise<T>::ptr promise_ptr;
00128             typedef T                        value_type;
00129 
00130             future( const promise_ptr& p = promise_ptr() )
00131             :m_prom(p){}
00132             future( const T& v ):m_prom( new promise<T>(v) ){}
00133 
00134             bool valid()const { return !!m_prom;       }
00135             bool ready()const { return m_prom->ready();}
00136             bool error()const { return valid() ? m_prom->error() : false; }
00137             operator const T&()const { 
00138                 if( !m_prom ) BOOST_THROW_EXCEPTION( error::null_future() );
00139                 return m_prom->wait();
00140             }
00141             const T& wait(const microseconds& timeout = microseconds::max() ) { 
00142                 if( !m_prom ) BOOST_THROW_EXCEPTION( error::null_future() );
00143                 return m_prom->wait(timeout); 
00144             }
00145 
00146         private:
00147             promise_ptr m_prom;
00148     };
00149 
00150     template<>
00151     class future<void> : public future<void_t> {
00152         public:
00153             future( const  promise<void_t>::ptr& p =  promise<void_t>::ptr() )
00154             :future<void_t>(p){}
00155             future( const void_t& v ):future<void_t>(v){}
00156     };
00157 
00158 
00159 } }
00160 
00161 
00162 #endif
 All Classes Namespaces Files Functions Variables Typedefs Defines