|
Boost : |
From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-02-10 16:59:46
> From: David Abrahams <dave_at_[hidden]>
> "Peter Dimov" <pdimov_at_[hidden]> writes:
> > It's a tool that allows high-level interfaces to be built. Whether
> > people will want/need to build their own high-level interfaces is
> > another story.
>
> I think it's a valuable question to ask whether /everyone/ will want
> to create /the same/ high-level interface ;-). In other words, as
> long as we have a bunch of low-level thread primitives, I prefer to
> reduce interface complexity and increase encapsulation unless we can
> find a specific use for a medium-level interface.
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";
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);
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);
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;
};
The async_result gives us the low level interface with a minimum of overhead, while the future gives us a higher level interface for ease of use. This higher level interface should even allow the syntax suggested elsewhere in this thread:
template <typename R, typename F, typename E>
future<R> execute(F function, E executor)
{
future<R> res(function);
executor(res);
return res;
}
template <typename F>
void thread_executor(F function)
{
thread thrd(function);
}
future<int> res = execute(foo, &thread_executor);
double d = res.result();
(And yes, I would offer these interfaces as well.)
Thoughts?
William E. Kempf
wekempf_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk