Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2003-02-10 17:38:32


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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk