模式的未来转换 [英] Pattern for future conversion

查看:125
本文介绍了模式的未来转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我们正在使用异步值非常沉重。
假设我有一个函数,确实是这样的:

currently we are using asynchronous values very heavily. Assume that I have a function which does something like this:

int do_something(const boost::posix_time::time_duration& sleep_time)
{
    BOOST_MESSAGE("Sleeping a bit");
    boost::this_thread::sleep(sleep_time);
    BOOST_MESSAGE("Finished taking a nap");

    return 42;
}

在code某个时刻,我们创造它创建了一个未来将由一个packaged_task设置这样一个int值的任务 - (worker_queue是一个boost :: ASIO :: io_service对象在这个例子中)是这样的:

At some point in code we create a task which creates a future to such an int value which will be set by a packaged_task - like this (worker_queue is a boost::asio::io_service in this example):

boost::unique_future<int> createAsynchronousValue(const boost::posix_time::seconds& sleep)
{
    boost::shared_ptr< boost::packaged_task<int> > task(
        new boost::packaged_task<int>(boost::bind(do_something, sleep)));
    boost::unique_future<int> ret = task->get_future();

    // Trigger execution
    working_queue.post(boost::bind(&boost::packaged_task<int>::operator (), task));

    return boost::move(ret);
}

在code还有一点我想换这个函数返回一些更高级别的对象,它也应该是未来。我需要一个转换函数,它接受的第一个值,并将其转换为另一个值(在我们的实际code,我们有一定的层次感,做异步RPC返回期货的反应 - 这些反应应转换为期货实物,吊舱甚至无效的将来能够在其上等待或捕获异常)。因此,这是在本实施例的转换功能:

At another point in code I want to wrap this function to return some higher level object which should also be a future. I need a conversion function which takes the first value and transforms it to another value (in our actual code we have some layering and doing asynchronous RPC which returns futures to responses - these responses should be converted to futures to real objects, PODs or even void future to be able to wait on it or catch exceptions). So this is the conversion function in this example:

float converter(boost::shared_future<int> value)
{
    BOOST_MESSAGE("Converting value " << value.get());
    return 1.0f * value.get();
}

这时我想作为升压文档描述只做如果想这种转换创建一个懒惰的未来:

Then I thought of creating a lazy future as described in the Boost docs to do this conversion only if wanted:

void invoke_lazy_task(boost::packaged_task<float>& task)
{
    try
    {
        task();
    }
    catch(boost::task_already_started&)
    {}
}

然后,我有一个函数(可能是更高层次的API)来创建一个包裹的未来:

And then I have a function (might be a higher level API) to create a wrapped future:

boost::unique_future<float> createWrappedFuture(const boost::posix_time::seconds& sleep)
{
    boost::shared_future<int> int_future(createAsynchronousValue(sleep));
    BOOST_MESSAGE("Creating converter task");
    boost::packaged_task<float> wrapper(boost::bind(converter, int_future));

    BOOST_MESSAGE("Setting wait callback");
    wrapper.set_wait_callback(invoke_lazy_task);

    BOOST_MESSAGE("Creating future to converter task");
    boost::unique_future<float> future = wrapper.get_future();

    BOOST_MESSAGE("Returning the future");
    return boost::move(future);
}

最后我希望能够用这样的:

At the end I want to be able to use it like this:

{    
    boost::unique_future<float> future = createWrappedFuture(boost::posix_time::seconds(1));
    BOOST_MESSAGE("Waiting for the future");
    future.wait();
    BOOST_CHECK_EQUAL(future.get(), 42.0f);
}

但在这里我最终得到约一个破碎的承诺例外。究其原因似乎是pretty明确对我来说,因为它执行转换packaged_task超出范围。

But here I end up getting an exception about a broken promise. The reason seems to be pretty clear for me because the packaged_task which does the conversion goes out of scope.

所以我的追问是:我该如何处理这种情况。我怎样才能prevent被破坏的任务吗?有没有一种模式,这?

So my questing is: How do I deal with such situations. How can I prevent the task from being destroyed? Is there a pattern for this?

最好成绩,

罗尼

推荐答案

您需要妥善管理任务对象的生命周期。

You need to manage the lifetime of task object properly.

最正确的方法是返回的boost :: packaged_task&LT;浮动&GT; 而不是的boost :: unique_future&LT;浮动&GT; createWrappedFuture()。主叫方将负责未来获取对象和prolongate任务生命周期,直到未来的价值已准备就绪。

The most correct way is to return boost::packaged_task<float> instead of boost::unique_future<float> from createWrappedFuture(). The caller will be responsible to get future object and to prolongate task lifetime until future value is ready.

或者你可以把任务对象为一些悬而未决的队列(全局或类成员)您在 createAsynchronousValue 也进行了类似的方式。但在这种情况下,你将需要explcitly管理任务的一生,完成后从队列中删除。所以不要以为这种解决方案具有的优势对返回任务,对象本身。

Or you can place task object into some 'pending' queue (global or class member) the similar way you did in createAsynchronousValue. But in this case you will need to explcitly manage task lifetime and remove it from queue after completion. So don't think this solution has advantages against returning task object itself.

这篇关于模式的未来转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆