动态分配的实现类std :: async-its其成员

时间:2015-06-05 07:20:41

标签: multithreading c++11 asynchronous shared-ptr

考虑使用标准异步接口的操作:

std::future<void> op();

在内部,op需要执行(可变)数量的异步操作才能完成;这些操作的数量是有限的但无限制的,并且取决于先前异步操作的结果。

这是一次(糟糕的)尝试:

/* An object of this class will store the shared execution state in the members;
*    the asynchronous op is its member. */
class shared
{
private:
    // shared state

private:
    // Actually does some operation (asynchronously).
    void do_op()
    {
        ...
        // Might need to launch more ops.
        if(...)
            launch_next_ops();
    }

public:
    // Launches next ops
    void launch_next_ops()
    {
        ...
        std::async(&shared::do_op, this);
    }
}

std::future<void> op()
{
    shared s;
    s.launch_next_ops();
    // Return some future of s used for the entire operation.
    ...
    // s destructed - delayed BOOM!
};

问题当然是s超出了范围,因此以后的方法不起作用。

要修改此内容,以下是更改:

class shared : public std::enable_shared_from_this<shared> 
{
private:
    /* The member now takes a shared pointer to itself; hopefully 
    *    this will keep it alive. */
    void do_op(std::shared_ptr<shared> p); // [*]

    void launch_next_ops()
    {
        ...
        std::async(&shared::do_op, this, shared_from_this());
    }
}

std::future<void> op()
{
    std::shared_ptr<shared> s{new shared{}};
    s->launch_next_ops();
    ...
};

(除了使用共享指针调用其方法的对象的古怪之外),问题在于标记为[*]的行。编译器(正确)警告它是一个未使用的变量。

当然,有可能以某种方式欺骗它,但这是否是一个基本问题的迹象?编译器是否有可能优化掉参数并使方法留下死对象?这整个计划有更好的替代方案吗?我发现最终的代码不是最直观的。

1 个答案:

答案 0 :(得分:1)

不,编译器不会优化掉参数。实际上,这是无关紧要的,因为终身扩展来自shared_from_this()被衰变复制( [thread.decaycopy] )绑定到调用std::async的结果中( [futures.async] / 3)。

如果您想避免使用未使用的参数的警告,请将其保留为未命名;警告未使用的参数的编译器不会对未使用的未命名参数发出警告。

另一种方法是制作do_op static,这意味着您必须使用其shared_ptr参数;这也解决了thisshared_from_this之间的重复问题。由于这非常麻烦,您可能希望使用lambda将shared_from_this转换为this指针:

std::async([](std::shared_ptr<shared> const& self){ self->do_op(); }, shared_from_this());

如果你可以使用C ++ 14 init-capture,那就更简单了:

std::async([self = shared_from_this()]{ self->do_op(); });