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

标签 multithreading c++11 asynchronous shared-ptr

考虑一个具有标准异步接口(interface)的操作:

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();
    ...
};

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

当然,有可能以某种方式欺骗它,但这是否表明存在根本问题?编译器是否有可能优化参数并留下死对象的方法?整个方案有更好的替代方案吗?我发现生成的代码不是最直观的。

最佳答案

不,编译器不会优化参数。事实上,这无关紧要,因为生命周期延长来自 shared_from_this()被衰减复制( [thread.decaycopy] )绑定(bind)到调用 std::async 的结果中( [futures.async] /3)。

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

另一种方法是制作 do_op static ,这意味着你必须使用它的 shared_ptr争论;这也解决了 this 之间的重复问题。和 shared_from_this .由于这相当麻烦,您可能希望使用 lambda 来转换 shared_from_thisthis指针:

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

如果您可以使用 C++14 初始化捕获,这将变得更加简单:
std::async([self = shared_from_this()]{ self->do_op(); });

关于multithreading - 动态分配的实现类 std::async-ing 其成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30660636/

相关文章:

函数指针的 C++11 HOWTO 模板别名

c# - 当尝试使用Task.Run()在MySql中运行插入查询时,它抛出以下异常: "Unable to connect to any of the specified MySQL hosts."

c++ - 中断已处于条件变量等待调用状态的 boost 线程

java - 破坏者消费者没有按预期工作

multithreading - 使用 netconn 同时处理多个 LwIP 连接

azure - 对 Azure 表存储的异步调用

node.js - 如何返回 Node.js 回调

C++11/C++03 和 std::vector 线程安全

C++ 在结构定义中初始化一个 vector

c++ - 接受对类模板参数的左值和右值引用