[英]C++20 stopping a detached std::jthread using an std::stop_token
In C++20 std::jthread
was introduced as a safer version of std::thread
;在 C++20 中,
std::jthread
被引入为std::thread
的更安全版本; where std::jthread
, as far as I understand, cleans up after itself when the thread exits.据我了解,其中
std::jthread
会在线程退出时自行清理。
Also, the concept of cooperative cancellation is introduced such that an std::jthread
manages an std::stop_source
that handles the state of the underlying thread, this std::stop_source
exposes an std::stop_token
that outsiders can use to read the state of the thread sanely.此外,引入了协作取消的概念,以便
std::jthread
管理一个处理底层线程状态的std::stop_source
::stop_source ,这个std::stop_source
公开了一个std::stop_token
,外人可以使用它来读取状态线程的理智。
What I have is something like this.我所拥有的是这样的。
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
is managed by a std::shared_ptr
, and there is no public constructor.注意
foo
由std::shared_ptr
管理,并且没有公共构造函数。
Somewhere along the line, another thread can call foo::stop_foo()
on a possibly detached thread.沿着这条线的某个地方,另一个线程可以在可能分离的线程上调用
foo::stop_foo()
。
Is what I am doing safe?我所做的安全吗?
Also, when detaching a thread, the C++ handle is no longer associated with the running thread, and the OS manages it, but does the thread keep receiving stop notifications from the std::stop_source
?此外,在分离线程时,C++ 句柄不再与正在运行的线程关联,由操作系统管理,但线程是否继续从
std::stop_source
接收停止通知?
Is there a better way to achieve what I need?有没有更好的方法来实现我所需要的? In MVSC, this doesn't seem to raise any exceptions or halt program execution, and I've done a lot of testing to verify this.
在 MVSC 中,这似乎不会引发任何异常或停止程序执行,我已经做了很多测试来验证这一点。
So, is this solution portable?那么,这个解决方案是否可移植?
What you wrote is potentially unsafe if the thread accesses this
after the foo
has been destroyed.如果线程在
foo
被销毁后访问this
,那么您编写的内容可能是不安全的。 It's also a bit convoluted.这也有点令人费解。 A simpler approach would just be to stick the jthread in the structure...
一种更简单的方法是将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
}
}
To match the semantics of your code, you would uncomment the jthr.detach()
in the destructor, but this is actually a bad idea since then you could end up destroying foo
while the thread is still accessing it.为了匹配代码的语义,您可以在析构函数中取消注释
jthr.detach()
,但这实际上是一个坏主意,因为那时您最终可能会在线程仍在访问它时销毁foo
。 The code I wrote above is safe, but obviously whichever thread drops the last reference to the foo
will have to wait for the jthread
to exit.我上面写的代码是安全的,但是很明显,无论哪个线程删除了对
foo
的最后一个引用,都必须等待jthread
退出。 If that's really intolerable, then maybe you want to change the API to stick a shared_ptr
in the thread itself, so that the thread can destroy foo
if it is still running after the last external reference is dropped.如果这真的令人无法忍受,那么也许您想更改 API 以在线程本身中粘贴一个
shared_ptr
,这样如果在删除最后一个外部引用后线程仍在运行,则该线程可以销毁foo
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.