![](/img/trans.png)
[英]Why does C++20 std::condition_variable not support std::stop_token?
[英]C++20 stopping a detached std::jthread using an std::stop_token
在 C++20 中, std::jthread
被引入为std::thread
的更安全版本; 据我了解,其中std::jthread
会在线程退出时自行清理。
此外,引入了协作取消的概念,以便std::jthread
管理一个处理底层线程状态的std::stop_source
::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();
}
}
注意foo
由std::shared_ptr
管理,并且没有公共构造函数。
沿着这条线的某个地方,另一个线程可以在可能分离的线程上调用foo::stop_foo()
。
我所做的安全吗?
此外,在分离线程时,C++ 句柄不再与正在运行的线程关联,由操作系统管理,但线程是否继续从std::stop_source
接收停止通知?
有没有更好的方法来实现我所需要的? 在 MVSC 中,这似乎不会引发任何异常或停止程序执行,我已经做了很多测试来验证这一点。
那么,这个解决方案是否可移植?
如果线程在foo
被销毁后访问this
,那么您编写的内容可能是不安全的。 这也有点令人费解。 一种更简单的方法是将jthread粘贴在结构中......
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
}
}
为了匹配代码的语义,您可以在析构函数中取消注释jthr.detach()
,但这实际上是一个坏主意,因为那时您最终可能会在线程仍在访问它时销毁foo
。 我上面写的代码是安全的,但是很明显,无论哪个线程删除了对foo
的最后一个引用,都必须等待jthread
退出。 如果这真的令人无法忍受,那么也许您想更改 API 以在线程本身中粘贴一个shared_ptr
,这样如果在删除最后一个外部引用后线程仍在运行,则该线程可以销毁foo
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.