X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fstd%2Fthread;h=ad383395ee9fe9413932fcf77bded8fe1db49fa4;hb=99dee82307f1e163e150c9c810452979994047ce;hp=e1bba0cb29b321d0d1e5a25861bdf415883005b5;hpb=bf1fc37bb4a3cab851e2acec811427d5243a22e9;p=thirdparty%2Fgcc.git diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index e1bba0cb29b3..ad383395ee9f 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// Copyright (C) 2008-2021 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -35,28 +35,20 @@ # include #else -#include - -#if defined(_GLIBCXX_HAS_GTHREADS) -#include - #include // std::chrono::* -#include // std::unique_ptr -#include // std::tuple #if __cplusplus > 201703L # include // std::strong_ordering # include // std::stop_source, std::stop_token, std::nostopstate #endif +#include // std::thread, get_id, yield + #ifdef _GLIBCXX_USE_NANOSLEEP # include // errno, EINTR # include // nanosleep #endif -#include // std::hash -#include // std::__invoke - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -69,238 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ - /// thread - class thread - { - public: - // Abstract base class for types that wrap arbitrary functors to be - // invoked in the new thread of execution. - struct _State - { - virtual ~_State(); - virtual void _M_run() = 0; - }; - using _State_ptr = unique_ptr<_State>; - - typedef __gthread_t native_handle_type; - - /// thread::id - class id - { - native_handle_type _M_thread; - - public: - id() noexcept : _M_thread() { } - - explicit - id(native_handle_type __id) : _M_thread(__id) { } - - private: - friend class thread; - friend class hash; - - friend bool - operator==(id __x, id __y) noexcept; - -#if __cpp_lib_three_way_comparison - friend strong_ordering - operator<=>(id __x, id __y) noexcept; -#else - friend bool - operator<(id __x, id __y) noexcept; -#endif - - template - friend basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __out, id __id); - }; - - private: - id _M_id; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2097. packaged_task constructors should be constrained - // 3039. Unnecessary decay in thread and packaged_task - template - using __not_same = __not_, thread>>; - - public: - thread() noexcept = default; - - template>> - explicit - thread(_Callable&& __f, _Args&&... __args) - { - static_assert( __is_invocable::type, - typename decay<_Args>::type...>::value, - "std::thread arguments must be invocable after conversion to rvalues" - ); - -#ifdef GTHR_ACTIVE_PROXY - // Create a reference to pthread_create, not just the gthr weak symbol. - auto __depend = reinterpret_cast(&pthread_create); -#else - auto __depend = nullptr; -#endif - // A call wrapper holding tuple{DECAY_COPY(__f), DECAY_COPY(__args)...} - using _Invoker_type = _Invoker<__decayed_tuple<_Callable, _Args...>>; - - _M_start_thread(_S_make_state<_Invoker_type>( - std::forward<_Callable>(__f), std::forward<_Args>(__args)...), - __depend); - } - - ~thread() - { - if (joinable()) - std::terminate(); - } - - thread(const thread&) = delete; - - thread(thread&& __t) noexcept - { swap(__t); } - - thread& operator=(const thread&) = delete; - - thread& operator=(thread&& __t) noexcept - { - if (joinable()) - std::terminate(); - swap(__t); - return *this; - } - - void - swap(thread& __t) noexcept - { std::swap(_M_id, __t._M_id); } - - bool - joinable() const noexcept - { return !(_M_id == id()); } - - void - join(); - - void - detach(); - - id - get_id() const noexcept - { return _M_id; } - - /** @pre thread is joinable - */ - native_handle_type - native_handle() - { return _M_id._M_thread; } - - // Returns a value that hints at the number of hardware thread contexts. - static unsigned int - hardware_concurrency() noexcept; - - private: - template - struct _State_impl : public _State - { - _Callable _M_func; - - template - _State_impl(_Args&&... __args) - : _M_func{{std::forward<_Args>(__args)...}} - { } - - void - _M_run() { _M_func(); } - }; - - void - _M_start_thread(_State_ptr, void (*)()); - - template - static _State_ptr - _S_make_state(_Args&&... __args) - { - using _Impl = _State_impl<_Callable>; - return _State_ptr{new _Impl{std::forward<_Args>(__args)...}}; - } -#if _GLIBCXX_THREAD_ABI_COMPAT - public: - struct _Impl_base; - typedef shared_ptr<_Impl_base> __shared_base_type; - struct _Impl_base - { - __shared_base_type _M_this_ptr; - virtual ~_Impl_base() = default; - virtual void _M_run() = 0; - }; - - private: - void - _M_start_thread(__shared_base_type, void (*)()); - - void - _M_start_thread(__shared_base_type); -#endif - - private: - // A call wrapper that does INVOKE(forwarded tuple elements...) - template - struct _Invoker - { - _Tuple _M_t; - - template - struct __result; - template - struct __result> - : __invoke_result<_Fn, _Args...> - { }; - - template - typename __result<_Tuple>::type - _M_invoke(_Index_tuple<_Ind...>) - { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); } - - typename __result<_Tuple>::type - operator()() - { - using _Indices - = typename _Build_index_tuple::value>::__type; - return _M_invoke(_Indices()); - } - }; - - template - using __decayed_tuple = tuple::type...>; - - public: - // Returns a call wrapper that stores - // tuple{DECAY_COPY(__callable), DECAY_COPY(__args)...}. - template - static _Invoker<__decayed_tuple<_Callable, _Args...>> - __make_invoker(_Callable&& __callable, _Args&&... __args) - { - return { __decayed_tuple<_Callable, _Args...>{ - std::forward<_Callable>(__callable), std::forward<_Args>(__args)... - } }; - } - }; - - inline void - swap(thread& __x, thread& __y) noexcept - { __x.swap(__y); } - - inline bool - operator==(thread::id __x, thread::id __y) noexcept - { - // pthread_equal is undefined if either thread ID is not valid, so we - // can't safely use __gthread_equal on default-constructed values (nor - // the non-zero value returned by this_thread::get_id() for - // single-threaded programs using GNU libc). Assume EqualityComparable. - return __x._M_thread == __y._M_thread; - } + // std::thread is defined in #if __cpp_lib_three_way_comparison inline strong_ordering @@ -332,17 +93,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__x < __y); } #endif // __cpp_lib_three_way_comparison - // DR 889. - /// std::hash specialization for thread::id. - template<> - struct hash - : public __hash_base - { - size_t - operator()(const thread::id& __id) const noexcept - { return std::_Hash_impl::hash(__id._M_thread); } - }; - template inline basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id) @@ -360,34 +110,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ namespace this_thread { - /// get_id - inline thread::id - get_id() noexcept - { -#ifdef __GLIBC__ - // For the GNU C library pthread_self() is usable without linking to - // libpthread.so but returns 0, so we cannot use it in single-threaded - // programs, because this_thread::get_id() != thread::id{} must be true. - // We know that pthread_t is an integral type in the GNU C library. - if (!__gthread_active_p()) - return thread::id(1); -#endif - return thread::id(__gthread_self()); - } - - /// yield - inline void - yield() noexcept - { -#ifdef _GLIBCXX_USE_SCHED_YIELD - __gthread_yield(); -#endif - } +#ifndef _GLIBCXX_NO_SLEEP +#ifndef _GLIBCXX_USE_NANOSLEEP void __sleep_for(chrono::seconds, chrono::nanoseconds); +#endif - /// sleep_for + /// this_thread::sleep_for template inline void sleep_for(const chrono::duration<_Rep, _Period>& __rtime) @@ -397,7 +127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __s = chrono::duration_cast(__rtime); auto __ns = chrono::duration_cast(__rtime - __s); #ifdef _GLIBCXX_USE_NANOSLEEP - __gthread_time_t __ts = + struct ::timespec __ts = { static_cast(__s.count()), static_cast(__ns.count()) @@ -409,7 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif } - /// sleep_until + /// this_thread::sleep_until template inline void sleep_until(const chrono::time_point<_Clock, _Duration>& __atime) @@ -430,12 +160,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __now = _Clock::now(); } } - } - - // @} group threads + } // namespace this_thread +#endif // ! NO_SLEEP #ifdef __cpp_lib_jthread + /// A thread that can be requested to stop and automatically joined. class jthread { public: @@ -471,7 +201,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator=(const jthread&) = delete; jthread& - operator=(jthread&&) noexcept = default; + operator=(jthread&& __other) noexcept + { + std::jthread(std::move(__other)).swap(*this); + return *this; + } void swap(jthread& __other) noexcept @@ -562,8 +296,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION thread _M_thread; }; #endif // __cpp_lib_jthread + + // @} group threads + _GLIBCXX_END_NAMESPACE_VERSION } // namespace -#endif // _GLIBCXX_HAS_GTHREADS #endif // C++11 #endif // _GLIBCXX_THREAD