|
Boost : |
Subject: Re: [boost] Futures Review - Should packaged_task be CopyConstructible?
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2009-01-26 17:00:31
Hi,
Currently when we set_wait_callback on a packaged_task, the packaged_task is given by reference to the callback function. This means that the packaged_task can not be moved.
As packaged_task is not CopyConstructible this limits quite a lot its use together with set_wait_callback. We need to pass it always by reference as functions parameters and can't be returned by a function.
I have tried to make a lazy_call function similar to spawn_task in the defined in N2709
template<typename F>
std::unique_future<typename std::result_of<F()>::type> spawn_task(F f)
{
typedef typename std::result_of<F()>::type result_type;
std::packaged_task<result_type()> task(std::move(f));
std::unique_future<result_type> res(task.get_future());
std::thread(std::move(task));
return res;
}
Here it is
template<typename F>
std::unique_future<typename std::result_of<F()>::type> lazy_call(F f)
{
typedef typename std::result_of<F()>::type result_type;
std::packaged_task<result_type> task(std::move(f));
task.set_wait_callback(invoke_lazy_task<result_type>())
std::unique_future<result_type> res(task.get_future());
return res;
}
but I need to return the packaged_task instead of the future because its lifetime must be longuer than the future->get() call. So I've tried to move the packaged_task which don't work either because the promise is broken
template<typename F>
std::packaged_task<typename std::result_of<F()>::type> lazy_call(F f)
{
typedef typename std::result_of<F()>::type result_type;
std::packaged_task<result_type> task(std::move(f));
task.set_wait_callback(invoke_lazy_task<result_type>())
return task;
}
Is there a way to implement this kind of function, other than wrapping the packaged_task on a CopyConstructible class?
template<typename F>
shared_ptr<std::packaged_task<typename std::result_of<F()>::type>> lazy_call(F f)
{
typedef typename std::result_of<F()>::type result_type;
shared_ptr<std::packaged_task<result_type>> task_ptr(new std::packaged_task<result_type()> (std::move(f)));
task_ptr->set_wait_callback(invoke_lazy_task<result_type>())
return task_ptr;
}
What is the rationale for making packaged_task movable only? Why should not be CopyConstructible?
Thanks,
Vicente
==========
template <typename T>
struct invoke_lazy_task {
typedef void result_type;
void operator()(packaged_task<T>& task) {
try {
task();
} catch(task_already_started&) {}
}
};
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk