假设我们有以下代码:
#include <iostream>
#include <future>
int main() {
auto packagedTask = std::packaged_task<int()>([] {
std::cout << "hello!\n";
return 10;
});
auto packagedTaskFuture = packagedTask.get_future();
auto packagedTaskPtr = std::make_shared<decltype(packagedTask)>(std::move(packagedTask));
auto v1 = packagedTaskFuture.valid(); // is valid
auto v2 = packagedTaskFuture.wait_for(std::chrono::seconds(0)); // timeout state
(*packagedTaskPtr)(); // execute task
auto v3 = packagedTaskFuture.wait_for(std::chrono::seconds(1)); // ready state
auto v4 = packagedTaskFuture.get(); // 10
return 0;
}
它在我的Visual Studio环境下运行完美,如您所见,我在将std::future
移至新创建的std::packaged_task
之前就检索了std::shared_ptr
。我已经研究了关于std::packaged_task
的C ++标准,因此§30.6.9.1packaged_task(packaged_task&& rhs) noexcept
第6页:
作用:构造一个新的packaged_task对象,并将rhs共享状态的所有权转让给* this,使rhs没有共享状态。将存储的任务从rhs移到* this。
,第30.6.9页第2页说:
当调用packaged_task对象时,将调用其存储的任务,并将结果(无论正常还是例外)存储在共享状态下。任何具有共享状态的期货都将能够访问存储的结果。
基于此信息,我有两个问题:
1)我说对了std::packaged_task
之后将std::future
链接到相同的std::move
吗?
2)在其他线程中使用我的std::shared_ptr
并在那里执行任务,并从当前线程中检查std::future
是否安全?
答案 0 :(得分:2)
因此,标准讨论的是(隐藏的)共享状态。共享状态在基于std::move
的副本上移动。
应该将对象(打包的任务,将来的对象)视为具有对该共享状态的引用的各种智能指针。
存在零竞争条件可能是由于该共享状态在多个线程中进行交互而引起的。唯一可能发生的竞争条件是,如果您正在多个线程中与同一 object 进行交互,并且在至少一个线程中调用了非{const
方法。
C ++并发原语中的“共享状态”是概念性的,不能保证甚至是一个对象。它没有方法。
是的,是的。