- auto __depend = nullptr;
-#endif
- _M_start_thread(_S_make_state(
- __make_invoker(std::forward<_Callable>(__f),
- std::forward<_Args>(__args)...)),
- __depend);
- }
-
- ~thread()
- {
- if (joinable())
- std::terminate();
- }
-
- 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();
-
- thread::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<typename _Callable>
- struct _State_impl : public _State
- {
- _Callable _M_func;
-
- _State_impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f))
- { }
-
- void
- _M_run() { _M_func(); }
- };
-
- void
- _M_start_thread(_State_ptr, void (*)());
-
- template<typename _Callable>
- static _State_ptr
- _S_make_state(_Callable&& __f)
- {
- using _Impl = _State_impl<_Callable>;
- return _State_ptr{new _Impl{std::forward<_Callable>(__f)}};
- }
-#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<typename _Tuple>
- struct _Invoker
- {
- _Tuple _M_t;
-
- template<size_t _Index>
- static __tuple_element_t<_Index, _Tuple>&&
- _S_declval();
-
- template<size_t... _Ind>
- auto
- _M_invoke(_Index_tuple<_Ind...>)
- noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
- -> decltype(std::__invoke(_S_declval<_Ind>()...))
- { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
-
- using _Indices
- = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
-
- auto
- operator()()
- noexcept(noexcept(std::declval<_Invoker&>()._M_invoke(_Indices())))
- -> decltype(std::declval<_Invoker&>()._M_invoke(_Indices()))
- { return _M_invoke(_Indices()); }
- };
-
- // Alias for _Invoker<tuple<DECAY_COPY(_Tp)...>>
- template<typename... _Tp>
- using __invoker_type
- = _Invoker<decltype(std::make_tuple(std::declval<_Tp>()...))>;
-
- public:
- // Returns a call wrapper that does
- // INVOKE(DECAY_COPY(__callable), DECAY_COPY(__args)).
- template<typename _Callable, typename... _Args>
- static __invoker_type<_Callable, _Args...>
- __make_invoker(_Callable&& __callable, _Args&&... __args)
- {
- return { {
- std::make_tuple(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;
- }
-