gpt4 book ai didi

c++ - std::async 的非阻塞调用:这个版本有多危险?

转载 作者:行者123 更新时间:2023-12-03 14:36:54 25 4
gpt4 key购买 nike

前段时间我正在寻找一种方法来调用 std::async无需存储std::future ,因此不会在范围结束时阻止执行。我找到了 this answer它使用捕获的 std::shared_ptr对于 std::future ,因此允许对 std::async 进行非阻塞调用.
推迟析构函数调用的另一种方法是完全阻止它被调用。这可以通过使用 operator new 的就地构造来实现。 .
考虑这个版本,它使用静态线程本地存储来进行就地构造 std::future<void> :

template <class F>
void call_async(F&& fun) {
thread_local uint8_t buf[sizeof(std::future<void>)] = {0};
auto fut = new(buf) std::future<void>();
*fut = std::async(std::launch::async, [fun]() {
fun();
});
}
这个版本不会产生任何与堆分配相关的开销,但它似乎非常非法,虽然我不确定为什么特别。
我知道在构造对象之前使用它是 UB,但事实并非如此。我不知道为什么不打电话 delete在这种情况下将在 UB 中解析(对于堆分配,它不是 UB)。
我看到的可能问题:
  • 多次调用一个对象的构造函数
  • 修改状态时的竞争条件(内部 std::promise 我想)

  • https://ideone.com/C44cfe
    更新
    每次调用移动分配时,直接在静态存储中构造一个对象(如 IlCapitano 所述)将阻塞(共享状态将被破坏,阻塞已删除对它的最后一个引用的线程)。
    由于未释放对共享状态的引用,不调用析构函数会导致泄漏。

    最佳答案

    结束一个非平凡对象的生命周期而不调用它的析构函数是未定义的行为,一旦有第二个 call_async 就会发生这种情况。调用。
    如果唯一的选择是未定义的行为,那么“与堆分配相关的开销”就是用词不当。 future返回者 async必须住在某个地方。
    更新后的代码定义了行为:它在启动下一个调用之前等待上一个调用完成。

    关于c++ - std::async 的非阻塞调用:这个版本有多危险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66902173/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com