Unlike
std::thread
, thejthread
logically holds an internal private member of typestd::stop_source
, which maintains a shared stop-state. (cppreference link)
I want to use an external std::stop_source
to control the stop behaviour of multiple threads in a coordinated way.
Example:
void thread_function(std::stop_token stoken)
{
while (!stoken.stop_requested())
{
// Do something
}
}
int main()
{
std::stop_source ssource; // common stop source
std::jthread t1(thread_function, ssource.get_token());
std::jthread t2(thread_function, ssource.get_token());
// ...
ssource.request_stop();
// ...
}
If I provide an std::stop_token
to a jthread
's constructor, does this prevent the jthread
from creating its own internal std::stop_source
, since an external stop_source
already exists?
The jthread
constructor merely forwards additional arguments to the function to be called. It does not do anything else with those parameters. In your code there are 3 stop sources, the ones of t1
and t2
are just not used to stop them.
From cppreference:
The new thread of execution starts executing:
std::invoke(decay-copy(std::forward<F>(f)), get_stop_token(), decay-copy(std::forward<Args>(args))...) (until C++23) std::invoke(auto(std::forward<F>(f)), get_stop_token(), auto(std::forward<Args>(args))...) (since C++23)
if the expression above is well-formed, otherwise starts executing:
std::invoke(decay-copy(std::forward<F>(f)), decay-copy(std::forward<Args>(args))...). (until C++23) std::invoke(auto(std::forward<F>(f)), auto(std::forward<Args>(args))...). (since C++23)
In different words: Either the callable you pass as first constructor argument has one parameter more than the number of arguments you pass and can accept a stop_token
. Then the constructor will pass its own stop_token
. If not, the jthread
constructor will not pass its own stop_token
but only forwards the arguments you passed.
In your example, the first variant is not well-formed because your function does take a single stop_token
which is included in Args...
. Though, the two threads t1
and t2
still have a stop_source
you can get via get_stop_source
(or their tokens via get_stop_token
).