I'm trying to work with the new jthreads and have started a std::jthread
where the operator() does get called, but I am unable to get it to stop. I want to create the thread by calling it as a function object.
my_thrd = std::make_shared<std::jthread>(&Test::operator(), &test);
If operater()
of my Test class is written as the following, it compiles:
void Test::operator()()
{
using namespace std::literals;
while (!token.stop_requested()) {
std::cout << "Working ...\n" << std::flush;
std::this_thread::sleep_for(5s);
}
close_connection();
}
But since it wasn't stopping, I thought I needed to somehow pass std::stop_token
to class Test
, like so.
void Test::operator()(std::stop_token token) { ... }
But this doesn't compile. I did change the header as well.
/usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/g -v10/thread: In instantiation of ‘static std::thread std::jthread::_S_create(std::stop_source&, _Callable&&, _Args&& ...) [with _Callable = void (Test::)(std::stop_token); _Args = {Test}]’: /usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/g -v10/thread:450:28: required from ‘std::jthread::jthread(_Callable&&, _Args&& ...) [with _Callable = void (Test::)(std::stop_token); _Args = {Test}; = void]’ /usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/g -v10/bits/stl_construct.h:97:14: required from ‘constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = std::jthread; _Args = {void (Test::)(std::stop_token), Test}; decltype (::new(void*(0)) _Tp) = std::jthread*]’ /usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/g -v10/bits/alloc_traits.h:514:4: required from ‘static constexpr void std::allocator_traitsstd::allocator<_CharT >::construct(std::allocator_traitsstd::allocator<_CharT >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::jthread; _Args = {void (Test::)(std::stop_token), Test}; _Tp = std::jthread; std::allocator_traitsstd::allocator<_CharT >::allocator_type = std::allocatorstd::jthread]’
Thoughts?
CodePudding user response:
You can use std::bind
to bind &test
to &Test::operator()
, then use std::placeholders::_1
to reserve a place for unbound std::stop_token
:
struct Test {
void operator()(std::stop_token token) {
using namespace std::literals;
while (!token.stop_requested()) {
std::cout << "Working ...\n" << std::flush;
std::this_thread::sleep_for(5s);
}
}
};
int main() {
Test test;
auto my_thrd = std::make_shared<std::jthread>(
std::bind(&Test::operator(), &test, std::placeholders::_1));
}
As @Nicol Bolas commented, we can also use C 20 std::bind_front
to do this, which is more lightweight and intuitive than std::bind
:
auto my_thrd = std::make_shared<std::jthread>(
std::bind_front(&Test::operator(), &test));