William E. Kempf wrote: > > How about this compromise: > > template <typename R> > class async_call > { > public: > template <typename F> > explicit async_call(const F& f) > : m_func(f) > { > } > > void operator()() > { > mutex::scoped_lock lock(m_mutex); > if (m_result) > throw "can't call multiple times";
operator() shouldn't throw; it's being used as a thread procedure, and the final verdict on these was to terminate() on exception, I believe. But you may have changed that. :-) > lock.unlock(); > R temp(m_func()); > lock.lock(); > m_result.reset(temp); > m_cond.notify_all(); > } > > R result() const > { > boost::mutex::scoped_lock lock(m_mutex); > while (!m_result) > m_cond.wait(lock); This changes result()'s semantics to "block until op() finishes"; what happens if nobody calls op()? Or it throws an exception? > return *m_result.get(); > } > > private: > boost::function0<R> m_func; > optional<R> m_result; > mutable mutex m_mutex; > mutable condition m_cond; > }; > > template <typename R> > class future > { > public: > template <typename F> > explicit future(const F& f) > : m_pimpl(new async_call<R>(f)) > { > } > > future(const future<R>& other) > { > mutex::scoped_lock lock(m_mutex); I don't think you need a lock here, but I may be missing something. > m_pimpl = other.m_pimpl; > } > > future<R>& operator=(const future<R>& other) > { > mutex::scoped_lock lock(m_mutex); -"- > m_pimpl = other.m_pimpl; > } > > void operator()() > { > (*get())(); > } > > R result() const > { > return get()->result(); > } > > private: > shared_ptr<async_call<R> > get() const > { > mutex::scoped_lock lock(m_mutex); -"- > return m_pimpl; > } > > shared_ptr<async_call<R> > m_pimpl; > mutable mutex m_mutex; > }; As for the "big picture", ask Dave. ;-) I tend towards a refcounted async_call. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost