Since clang-tidy was complaining about "The parameter 'stop_token' is copied for each invocation but only used as a const reference; consider making it a const reference" I was asking myself the question, why every example I find about std::jthread/stop_token takes the stop_token by value, but I did not find any explanation for it.
So, why take the stop_token by value?
1) void f(std::stop_token){};
2) void f(const std::stop_token&){};
Does it really matter when you can assume that the stop_token is the one generated by std::jthread?
edit: This is asked purely out of curiosity and to not ignore a clang-tidy warning "just because".
CodePudding user response:
As per cppref,
Creates new jthread object and associates it with a thread of execution. The new thread of execution starts executing
std::invoke(std::move(f_copy), get_stop_token(), std::move(args_copy)...)
, ...
And the return type of std::jthread::get_stop_token
is std::stop_token
.
So, if your f
is only used to construct a std::jthread
, I believe it's totally ok to be with a const std::stop_token&
as its first parameter. There's no lifetime issue.
But if you want to use your f
in other places, std::thread
for example, there may be a problem.
void f(const std::stop_token&) {}
{
std::stop_source ssrc;
std::stop_token stk{ssrc.get_token()};
std::thread t{f, std::ref(stk)};
}
When stk
gets destroyed, the reference is dangled.
In most cases, you should pass by value.
Because copying std::stop_token
and std::stop_source
is relative cheap.
Also, since std::token
is usually stored in a lambda and/or used in another thread, passing by value can avoid lifetime issues.
There're also some cases where you could pass by reference.
Since it's not that cheap compared to raw pointers. It'll be more efficient to pass by reference if you can guarantee the lifetime.
For example, std::stop_callback
's constructor, because it'll copy std::stop_token
inside, pass by reference will be better.
template<class C>
explicit stop_callback( const std::stop_token& st, C&& cb ) noexcept(/*see below*/);