00001 #ifndef toast_async_promise_hpp_INCLUDED
00002 #define toast_async_promise_hpp_INCLUDED
00003
00004 #include <boost/type_traits.hpp>
00005 #include <boost/optional.hpp>
00006 #include <boost/shared_ptr.hpp>
00007 #include <boost/weak_ptr.hpp>
00008 #include <boost/function.hpp>
00009 #include <boost/bind.hpp>
00010 #include <boost/thread/condition.hpp>
00011 #include <toast/async/thread_specific_request_queue.hpp>
00012
00013 namespace toast {
00014 namespace async {
00015
00016 namespace detail {
00017 template <typename T>
00018 struct promise_data
00019 {
00020 typedef T value_type;
00021 boost::optional<T> value;
00022 boost::mutex mutex;
00023 boost::condition condition;
00024 };
00025
00026 template <typename PromiseType, typename PromiseValueType>
00027 void set_data(PromiseType &pd, PromiseValueType const &t)
00028 {
00029 boost::mutex::scoped_lock lock(pd.mutex);
00030 if(pd.value)
00031 return;
00032 pd.value = t;
00033 pd.condition.notify_all();
00034 }
00035
00036 template <typename T, typename U>
00037 void set_shared_data(T data,
00038 U const &f)
00039 {
00040 set_data(*data, f());
00041 }
00042 }
00043
00044 template <typename T> class promise;
00045
00052 template <typename T>
00053 promise<T> future(const boost::function<T()>&, worker_pool&);
00054
00063 template <typename T>
00064 class promise
00065 {
00066 private:
00067 mutable boost::shared_ptr<detail::promise_data<T> > data_;
00068 void wait_until_defined() const
00069 {
00070 boost::mutex::scoped_lock lock(data_->mutex);
00071 while(!data_->value)
00072 data_->condition.wait(lock);
00073 }
00074 public:
00075 typedef void (promise::*unspecified_bool_type)() const;
00076
00078 promise() : data_(new detail::promise_data<T>()) {}
00079 promise(boost::shared_ptr<detail::promise_data<T> > data) : data_(data) {}
00080
00083 promise &operator=(T const &t)
00084 {
00085 detail::set_data(*data_, t);
00086 return data_->value;
00087 }
00089 const T &operator*() const
00090 {
00091 wait_until_defined();
00092 return *(data_->value);
00093 }
00095 const T *operator->() const
00096 {
00097 wait_until_defined();
00098 return data_->value.get_ptr();
00099 }
00101 operator unspecified_bool_type () const
00102 {
00103 boost::mutex::scoped_lock lock(data_->mutex);
00104 return data_->value ? &promise::wait_until_defined : 0;
00105 }
00106 };
00107
00110 template <typename T>
00111 promise<T> future(boost::function<T ()> const &f, worker_pool &pool =
00112 default_worker_pool())
00113 {
00114 boost::shared_ptr<detail::promise_data<T> > p(new detail::promise_data<T>());
00115 pool.push(boost::bind(&detail::set_shared_data<
00116 boost::shared_ptr< detail::promise_data<T> >,
00117 boost::function<T ()> >,
00118 p, f));
00119 return promise<T>(p);
00120 }
00121
00124 }
00125 }
00126
00127 #endif // toast_async_promise_hpp_INCLUDED