https://gcc.gnu.org/g:36ab9b9c6747032bc6b4b3aae49202a7f30bf4c4
commit r16-3397-g36ab9b9c6747032bc6b4b3aae49202a7f30bf4c4 Author: Tomasz KamiĆski <tkami...@redhat.com> Date: Thu Aug 21 18:00:25 2025 +0200 libstdc++: Specialize _Never_valueless_alt for jthread, stop_token and stop_source The move constructors for stop_source and stop_token are equivalent to copying and clearing the raw pointer, as they are wrappers for a counted-shared state. For jthread, the move constructor performs a member-wise move of stop_source and thread. While std::thread could also have a _Never_valueless_alt specialization due to its inexpensive move (only moving a handle), doing so now would change the ABI. This patch takes the opportunity to correct this behavior for jthread, before C++20 API is marked stable. libstdc++-v3/ChangeLog: * include/std/stop_token (__variant::_Never_valueless_alt): Declare. (__variant::_Never_valueless_alt<std::stop_token>) (__variant::_Never_valueless_alt<std::stop_source>): Define. * include/std/thread: (__variant::_Never_valueless_alt): Declare. (__variant::_Never_valueless_alt<std::jthread>): Define. Diff: --- libstdc++-v3/include/std/stop_token | 19 +++++++++++++++++++ libstdc++-v3/include/std/thread | 14 ++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/libstdc++-v3/include/std/stop_token b/libstdc++-v3/include/std/stop_token index 775ec6aa207d..b593daff392b 100644 --- a/libstdc++-v3/include/std/stop_token +++ b/libstdc++-v3/include/std/stop_token @@ -648,6 +648,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Callback> stop_callback(stop_token, _Callback) -> stop_callback<_Callback>; + /// @cond undocumented + namespace __detail::__variant + { + template<typename> struct _Never_valueless_alt; // see <variant> + + // Provide the strong exception-safety guarantee when emplacing a + // stop_token or stop_source into a variant. + template<> + struct _Never_valueless_alt<std::stop_token> + : true_type + { }; + + template<> + struct _Never_valueless_alt<std::stop_source> + : true_type + { }; + } // namespace __detail::__variant + /// @endcond + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __glibcxx_jthread diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 0de08c0bd3e3..94ded714e9e0 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -294,6 +294,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION stop_source _M_stop_source; thread _M_thread; }; + + /// @cond undocumented + namespace __detail::__variant + { + template<typename> struct _Never_valueless_alt; // see <variant> + + // Provide the strong exception-safety guarantee when emplacing a + // jthread into a variant. + template<> + struct _Never_valueless_alt<std::jthread> + : true_type + { }; + } // namespace __detail::__variant + /// @endcond #endif // __cpp_lib_jthread #ifdef __cpp_lib_formatters // C++ >= 23