C++ Logo

std-proposals

Advanced search

[std-proposals] std::jthread - Invoke member function pointer with stop_token

From: Kilian Henneberger <kilis-mail_at_[hidden]>
Date: Sun, 9 Jul 2023 18:03:19 +0200
Hello,

C++20 added std::jthread. One of the differences compared to std::thread
is, that std::jthread can provide a std::stop_token to the new thread of
execution.

Example:
auto f = [](std::stop_token stoken) { //stoken is a std::stop_token,
associated to our std::jthread thr1
     while (!stoken.stop_requested()) {
         // do some work...
     }
};
std::jthread thr1(f);

We construct a std::jthread thr1, which internally holds a
std::stop_source and passes an associated std::stop_token to a copy of
our lambda expression f. So far, so good. std::jthread
usesis_invocable_v<decay_t<F>, stop_token, decay_t<Args>...> to
determine if the callable F can be invoked with a std::stop_token.
Unfortunately, this leads to the effect, that following code will not
compile:
struct T {
     void ThreadFunc(std::stop_token stoken) { }
};

int main() {
     T obj;
     std::jthread thr(&T::ThreadFunc, &obj); // error here
}

The issue is, that the std::stop_token is passed to /INVOKE/ before the
object-pointer &obj. So it checks if /INVOKE(&T::ThreadFunc,
get_stop_token(), &obj)/ is valid, which it is not. To make the sample
work, a simple workaround could be to write
int main() {
     T obj;
     std::jthread thr(std::bind_front(&T::ThreadFunc, &obj)); //Or
(since P2714): std::bind_front<&T::ThreadFunc>(&obj)
}

The workaround is fairly simple. Nevertheless, I think that the current
behavior of std::jthread's constructor is surprising. Personally, I
would have expected, that if I pass a member function pointer to the
constructor of std::jthread, that it then checks for
is_invocable_v<decay_t<F>, decay_t<Arg0>, stop_token,
decay_t<OtherArgs>...>. This idea has already been discussed here:
https://www.mail-archive.com/gcc-bugs_at_[hidden]/msg690638.html . As a
result, it got implemented as an extension to libstdc++
(https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/thread#L246).
I am almost sure it would be worth standardizing this extension. But I
first want to float the idea here and collect some feedback.

Thanks and best regards,
Kilian

Received on 2023-07-09 16:03:29