* [PATCH] libstdc++: Optimize std::jthread construction
@ 2019-11-16 21:47 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2019-11-16 21:47 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1192 bytes --]
This change avoids storing a copy of a stop_token object that isn't
needed and won't be passed to the callable object. This slightly reduces
memory usage when the callable doesn't use a stop_token. It also removes
indirection in the invocation of the callable in the new thread, as
there is no lambda and no additional calls to std::invoke.
It also adds some missing [[nodiscard]] attributes, and the non-member
swap overload for std::jthread.
* include/std/thread (jthread::jthread()): Use nostopstate constant.
(jthread::jthread(Callable&&, Args&&...)): Use helper function to
create std::thread instead of indirection through a lambda. Use
remove_cvref_t instead of decay_t.
(jthread::joinable(), jthread::get_id(), jthread::native_handle())
(jthread::hardware_concurrency()): Add nodiscard attribute.
(swap(jthread&. jthread&)): Define hidden friend.
(jthread::_S_create): New helper function for constructor.
Tested powerpc64le-linux, committed to trunk.
As discussed with Tom, we also plan to replace the use of shared_ptr
in stop_source and stop_token with something more lightweight, that
doesn't store a weak count and two copies of the pointer.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 4647 bytes --]
commit 650ad104007e2f3474d735ec642b7613886cfcfe
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Sat Nov 16 21:32:05 2019 +0000
libstdc++: Optimize std::jthread construction
This change avoids storing a copy of a stop_token object that isn't
needed and won't be passed to the callable object. This slightly reduces
memory usage when the callable doesn't use a stop_token. It also removes
indirection in the invocation of the callable in the new thread, as
there is no lambda and no additional calls to std::invoke.
It also adds some missing [[nodiscard]] attributes, and the non-member
swap overload for std::jthread.
* include/std/thread (jthread::jthread()): Use nostopstate constant.
(jthread::jthread(Callable&&, Args&&...)): Use helper function to
create std::thread instead of indirection through a lambda. Use
remove_cvref_t instead of decay_t.
(jthread::joinable(), jthread::get_id(), jthread::native_handle())
(jthread::hardware_concurrency()): Add nodiscard attribute.
(swap(jthread&. jthread&)): Define hidden friend.
(jthread::_S_create): New helper function for constructor.
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index 93afa766d18..010921b2160 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -425,31 +425,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using native_handle_type = std::thread::native_handle_type;
jthread() noexcept
- : _M_stop_source{ nostopstate_t{ } }
+ : _M_stop_source{nostopstate}
{ }
template<typename _Callable, typename... _Args,
- typename = std::enable_if_t<!std::is_same_v<std::decay_t<_Callable>, jthread>>>
- explicit
- jthread(_Callable&& __f, _Args&&... __args)
- : _M_thread{[](stop_token __token, auto&& __cb, auto&&... __args)
- {
- if constexpr(std::is_invocable_v<_Callable, stop_token, _Args...>)
- {
- std::invoke(std::forward<decltype(__cb)>(__cb),
- std::move(__token),
- std::forward<decltype(__args)>(__args)...);
- }
- else
- {
- std::invoke(std::forward<decltype(__cb)>(__cb),
- std::forward<decltype(__args)>(__args)...);
- }
- },
- _M_stop_source.get_token(),
- std::forward<_Callable>(__f),
- std::forward<_Args>(__args)...}
- { }
+ typename = enable_if_t<!is_same_v<remove_cvref_t<_Callable>,
+ jthread>>>
+ explicit
+ jthread(_Callable&& __f, _Args&&... __args)
+ : _M_thread{_S_create(_M_stop_source, std::forward<_Callable>(__f),
+ std::forward<_Args>(__args)...)}
+ { }
jthread(const jthread&) = delete;
jthread(jthread&&) noexcept = default;
@@ -476,7 +462,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::swap(_M_thread, __other._M_thread);
}
- bool
+ [[nodiscard]] bool
joinable() const noexcept
{
return _M_thread.joinable();
@@ -494,19 +480,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_thread.detach();
}
- id
+ [[nodiscard]] id
get_id() const noexcept
{
_M_thread.get_id();
}
- native_handle_type
+ [[nodiscard]] native_handle_type
native_handle()
{
return _M_thread.native_handle();
}
- static unsigned
+ [[nodiscard]] static unsigned
hardware_concurrency() noexcept
{
return std::thread::hardware_concurrency();
@@ -529,7 +515,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return get_stop_source().request_stop();
}
+ friend void swap(jthread& __lhs, jthread& __rhs) noexcept
+ {
+ __lhs.swap(__rhs);
+ }
+
private:
+ template<typename _Callable, typename... _Args>
+ static thread
+ _S_create(stop_source& __ssrc, _Callable&& __f, _Args&&... __args)
+ {
+ if constexpr(is_invocable_v<_Callable, stop_token, _Args...>)
+ return thread{std::forward<_Callable>(__f), __ssrc.get_token(),
+ std::forward<_Args>(__args)...};
+ else
+ return thread{std::forward<_Callable>(__f),
+ std::forward<_Args>(__args)...};
+ }
+
stop_source _M_stop_source;
std::thread _M_thread;
};
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2019-11-16 21:47 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-16 21:47 [PATCH] libstdc++: Optimize std::jthread construction Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).