提问人:HashAL78 提问时间:6/30/2022 最后编辑:HashAL78 更新时间:6/30/2022 访问量:920
C++20 使用 std::stop_token 停止分离的 std::jthread
C++20 stopping a detached std::jthread using an std::stop_token
问:
在 C++ 中,20 被引入为更安全的版本;据我了解,当线程退出时,它会自行清理。std::jthread
std::thread
std::jthread
此外,还引入了合作取消的概念,以便管理处理底层线程状态的 an,这暴露了外部人员可以使用它来理智地读取线程状态。std::jthread
std::stop_source
std::stop_source
std::stop_token
我所拥有的是这样的。
class foo {
std::stop_token stok;
std::stop_source ssource;
public:
void start_foo() {
// ...
auto calculation = [this](std::stop_token inner_tok) {
// ... (*this is used here)
while(!inner_tok.stop_requested()) {
// stuff
}
}
auto thread = std::jthread(calculation);
ctok = thread.get_stop_token();
ssource = thread.get_stop_source();
thread.detach(); // ??
}
void stop_foo() {
if (ssource.stop_possible()) {
ssource.request_stop();
}
}
~foo() {
stop_foo();
}
}
Note 由 管理,并且没有公共构造函数。foo
std::shared_ptr
在线路的某个位置,另一个线程可以调用可能分离的线程。foo::stop_foo()
我正在做的事情安全吗?
此外,分离线程时,C++ 句柄不再与正在运行的线程关联,操作系统对其进行管理,但线程是否不断接收来自 ?std::stop_source
有没有更好的方法来实现我需要的东西?在 MVSC 中,这似乎不会引发任何异常或停止程序执行,我已经做了很多测试来验证这一点。
那么,这个解决方案是便携式的吗?
答:
如果线程在销毁后访问,则您编写的内容可能不安全。这也有点令人费解。一个更简单的方法是将 jthread 粘贴在结构中......this
foo
class foo {
std::jthread thr;
public:
void start_foo() {
// ...
jthr = std::jthread([this](std::stop_token inner_tok) {
// ... (*this is used here)
while(!inner_tok.stop_requested()) {
// stuff
}
});
}
void stop_foo() {
jthr.request_stop();
}
~foo() {
stop_foo();
// jthr.detatch(); // this is a bad idea
}
}
为了匹配代码的语义,您可以在析构函数中取消注释,但这实际上是一个坏主意,因为这样您最终可能会在线程仍在访问它时销毁它。我上面写的代码是安全的,但显然,无论哪个线程删除了对 的最后一个引用,都必须等待 退出。如果这真的无法忍受,那么也许您想将 API 更改为在线程本身中粘贴 a,以便在删除最后一个外部引用后线程仍在运行时可以销毁。jthr.detach()
foo
foo
jthread
shared_ptr
foo
评论
start_foo()
foo
stop_source
stop_source
foo
jthread
foo::stop_foo
超出范围时自动停止” - 你的意思是。无论如何,该问题只是因为您声明为 的局部变量。如果您将其存储为类成员(就像您存储的 and 一样,然后可以将其作为局部变量移动到中),那么分离就不再是问题了。 如果线程正在运行,仍然可以停止线程,并且可以在停止线程后停止线程以确保它干净地结束start_foo()
thread
start_foo()
stop_source
stop_token
stop_foo()
stop_foo()
~foo()
join()
计算
时被阻塞”——即使你不分离线程,Ted 所说的任何事情都不会导致这种情况发生。基本上,这只有在主线程尝试但没有结束的情况下才会发生(例如,因为死锁)。join()
jthread
jthread