diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2015-09-29 13:54:05 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2015-09-29 13:54:05 +0100 |
commit | ce535a9685b11c846560cc0f9f4dded1ca558efc (patch) | |
tree | 1c41b68da533870ce3a44a9dd4a934252561bfbf /libstdc++-v3/src | |
parent | c357b903daa3f831a34541a9d99469ccce226d54 (diff) | |
download | gcc-ce535a9685b11c846560cc0f9f4dded1ca558efc.zip gcc-ce535a9685b11c846560cc0f9f4dded1ca558efc.tar.gz gcc-ce535a9685b11c846560cc0f9f4dded1ca558efc.tar.bz2 |
Reduce space and time overhead of std::thread
PR libstdc++/65393
* config/abi/pre/gnu.ver: Export new symbols.
* include/std/thread (thread::_State, thread::_State_impl): New types.
(thread::_M_start_thread): Add overload taking unique_ptr<_State>.
(thread::_M_make_routine): Remove.
(thread::_S_make_state): Add.
(thread::_Impl_base, thread::_Impl, thread::_M_start_thread)
[_GLIBCXX_THREAD_ABI_COMPAT] Only declare conditionally.
* src/c++11/thread.cc (execute_native_thread_routine): Rename to
execute_native_thread_routine_compat and re-define to use _State.
(thread::_State::~_State()): Define.
(thread::_M_make_thread): Define new overload.
(thread::_M_make_thread) [_GLIBCXX_THREAD_ABI_COMPAT]: Only define old
overloads conditionally.
From-SVN: r228242
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/c++11/thread.cc | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc index 906cafa..e116afa 100644 --- a/libstdc++-v3/src/c++11/thread.cc +++ b/libstdc++-v3/src/c++11/thread.cc @@ -23,6 +23,7 @@ // <http://www.gnu.org/licenses/>. +#define _GLIBCXX_THREAD_ABI_COMPAT 1 #include <thread> #include <system_error> #include <cerrno> @@ -75,8 +76,33 @@ namespace std _GLIBCXX_VISIBILITY(default) extern "C" void* execute_native_thread_routine(void* __p) { + thread::_State_ptr __t{ static_cast<thread::_State*>(__p) }; + + __try + { + __t->_M_run(); + } + __catch(const __cxxabiv1::__forced_unwind&) + { + __throw_exception_again; + } + __catch(...) + { + std::terminate(); + } + + return nullptr; + } + +#if _GLIBCXX_THREAD_ABI_COMPAT + extern "C" void* + execute_native_thread_routine_compat(void* __p) + { thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p); thread::__shared_base_type __local; + // Now that a new thread has been created we can transfer ownership of + // the thread state to a local object, breaking the reference cycle + // created in thread::_M_start_thread. __local.swap(__t->_M_this_ptr); __try @@ -94,10 +120,13 @@ namespace std _GLIBCXX_VISIBILITY(default) return nullptr; } +#endif } _GLIBCXX_BEGIN_NAMESPACE_VERSION + thread::_State::~_State() = default; + void thread::join() { @@ -127,6 +156,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } void + thread::_M_start_thread(_State_ptr state, void (*)()) + { + const int err = __gthread_create(&_M_id._M_thread, + &execute_native_thread_routine, + state.get()); + if (err) + __throw_system_error(err); + state.release(); + } + +#if _GLIBCXX_THREAD_ABI_COMPAT + void thread::_M_start_thread(__shared_base_type __b) { if (!__gthread_active_p()) @@ -144,15 +185,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION thread::_M_start_thread(__shared_base_type __b, void (*)()) { auto ptr = __b.get(); + // Create a reference cycle that will be broken in the new thread. ptr->_M_this_ptr = std::move(__b); int __e = __gthread_create(&_M_id._M_thread, - &execute_native_thread_routine, ptr); + &execute_native_thread_routine_compat, ptr); if (__e) { - ptr->_M_this_ptr.reset(); + ptr->_M_this_ptr.reset(); // break reference cycle, destroying *ptr. __throw_system_error(__e); } } +#endif unsigned int thread::hardware_concurrency() noexcept |