大佬教程收集整理的这篇文章主要介绍了如何使用 std::jthread,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我对如何安全地为 jthread
注册回调有点困惑。您需要 token
,这意味着您需要在创建 jthread
之后进行注册,这意味着回调将在 jthread
之前销毁。在下面的示例中,cb5
和 cb6
显然在 jthread
的 dtor 启动之前被销毁,因此它们会自动注销自己并且永远不会执行。相反,cb1
和 cb2
在销毁 jthread
后被显式销毁,因此它们可以保证作为请求停止的 dtor 的副作用执行。现在令人困惑的部分是我找不到任何保证 cb3
和 cb4
保证执行的保证。例如,我找不到任何内容表明请求停止会自动更改设置停止标志并执行所有回调。另一方面,我查看了 request_stop
的 Implementation:223,它似乎执行以下操作@H_403_27@
现在终于到问题了,根据上述,cb3
和 cb4
的执行正在与它们的析构函数竞争(至少 cb3
,因为 cb4
将是选择在将用于设置停止标志的同一锁下执行,但我再次找不到对某处提到的 cb4
的保证)。那么如何在不显式调用 stop_callBACk
的情况下正确地将 jthread
与 request_stop
一起使用?您不能在之后注册回调,因为它们会在 cb5
和 cb6
之前被销毁,并且您不能在线程中注册它们,因为它们不能保证像 cb3
和cb4
并且我不认为这是为了以cb1
和 cb2
@H_403_27@ 的复杂方式延长它们的使用寿命
#include <chrono> #include <iostream> #include <stop_token> #include <thread> int main(int argc,const char * const * const argv) { using namespace std::chrono_literals; const auto _cb1 = []() -> voID { std::cout << "cb1\n"; std::this_thread::yIEld(); std::this_thread::sleep_for(10s); }; const auto _cb2 = []() -> voID { std::cout << "cb2\n"; std::this_thread::yIEld(); std::this_thread::sleep_for(10s); }; using CB1 = decltype(std::stop_callBACk(std::declval<std::stop_token>(),_cb1)); using CB2 = decltype(std::stop_callBACk(std::declval<std::stop_token>(),_cb2)); std::byte storage1[sizeof(CB1)]; std::byte storage2[sizeof(CB2)]; const cB1 * cb1 = nullptr; const cB2 * cb2 = nullptr; { std::jthread worker([](const std::stop_token & stop_token) { std::stop_callBACk cb3(stop_token,[] { std::cout << "cb3\n"; std::this_thread::yIEld(); std::this_thread::sleep_for(10s); }); std::stop_callBACk cb4(stop_token,[] { std::cout << "cb4\n"; std::this_thread::yIEld(); std::this_thread::sleep_for(10s); }); while (!stop_token.stop_requested()) { } }); cb1 = new (&storage1) std::stop_callBACk(worker.get_stop_token(),_cb1); cb2 = new (&storage2) std::stop_callBACk(worker.get_stop_token(),_cb2); std::stop_callBACk cb5(worker.get_stop_token(),[] { std::cout << "cb5\n"; std::this_thread::yIEld(); std::this_thread::sleep_for(10s); }); std::stop_callBACk cb6(worker.get_stop_token(),[] { std::cout << "cb6\n"; std::this_thread::yIEld(); std::this_thread::sleep_for(10s); }); std::this_thread::sleep_for(2s); } cb1->~CB1(); cb2->~CB2(); return 0; }
@H_301_75@解决方法
标准directly states that:
返回 true 的对
request_stop
的调用与返回 true 的关联stop_requested
或stop_token
对象上的stop_source
调用同步。这意味着对返回
stop_requested
的true
的调用“发生在”任何返回request_stop
的true
之后。因此,您的while
循环无法退出,直到对request_stop
的调用实际将true
返回给某个线程。更重要的是,它不能退出,直到这样的调用返回。
request_stop
是 explicitly stated 到:如果发出请求,则同步调用关联
stop_callBACk
对象注册的回调。被“同步”调用意味着:这个函数要么在请求停止的线程上调用它们,要么与它们被调用的任何线程同步。重点是,在这些回调完成之前,此函数不会返回。
并且在此函数返回之前,
stop_requested
不会返回true
,如前所述。所以没有数据竞争。线程退出前回调不会被销毁。
以上是大佬教程为你收集整理的如何使用 std::jthread全部内容,希望文章能够帮你解决如何使用 std::jthread所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。