Index: include/std/thread =================================================================== --- include/std/thread (revision 171022) +++ include/std/thread (working copy) @@ -48,7 +48,6 @@ namespace std _GLIBCXX_VISIBILITY(default) { -_GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @defgroup threads Threads @@ -58,36 +57,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ + _GLIBCXX_END_NAMESPACE_VERSION + namespace this_thread + { + _GLIBCXX_BEGIN_NAMESPACE_VERSION + class __this_thread; + _GLIBCXX_END_NAMESPACE_VERSION + } + +_GLIBCXX_BEGIN_NAMESPACE_VERSION /// thread class thread { public: typedef __gthread_t native_handle_type; struct _Impl_base; - typedef shared_ptr<_Impl_base> __shared_base_type; + struct _Impl_base2; + typedef shared_ptr<_Impl_base> __compat_base_type; + typedef shared_ptr<_Impl_base2> __shared_base_type; /// thread::id class id { - native_handle_type _M_thread; - public: - id() : _M_thread() { } - - explicit - id(native_handle_type __id) : _M_thread(__id) { } + constexpr id() : _M_id() { } private: + explicit id(size_t __id) noexcept : _M_id(__id) { } + + size_t _M_id; + friend class thread; friend class hash; + friend class this_thread::__this_thread; friend bool - operator==(thread::id __x, thread::id __y) - { return __gthread_equal(__x._M_thread, __y._M_thread); } + operator==(thread::id __x, thread::id __y) noexcept + { return __x._M_id == __y._M_id; } friend bool - operator<(thread::id __x, thread::id __y) - { return __x._M_thread < __y._M_thread; } + operator<(thread::id __x, thread::id __y) noexcept + { return __x._M_id < __y._M_id; } template friend basic_ostream<_CharT, _Traits>& @@ -105,8 +115,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION virtual void _M_run() = 0; }; + struct _Impl_base2 : _Impl_base + { + native_handle_type _M_thread; + id _M_id; + + _Impl_base2() = default; + + _Impl_base2(const _Impl_base2&) = delete; + _Impl_base2& operator=(const _Impl_base2&) = delete; + }; + + private: template - struct _Impl : public _Impl_base + struct _Impl : public _Impl_base2 { _Callable _M_func; @@ -117,8 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_run() { _M_func(); } }; - private: - id _M_id; + __shared_base_type _M_impl; public: thread() = default; @@ -132,7 +153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION explicit thread(_Callable&& __f, _Args&&... __args) { - _M_start_thread(_M_make_routine(std::bind( + _M_start_thread2(_M_make_routine(std::bind( std::forward<_Callable>(__f), std::forward<_Args>(__args)...))); } @@ -155,11 +176,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(thread& __t) - { std::swap(_M_id, __t._M_id); } + { std::swap(_M_impl, __t._M_impl); } bool joinable() const - { return !(_M_id == id()); } + { return !(get_id() == id()); } void join(); @@ -169,13 +190,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION thread::id get_id() const - { return _M_id; } + { return _M_impl ? _M_impl->_M_id : id(); } /** @pre thread is joinable */ native_handle_type native_handle() - { return _M_id._M_thread; } + { return _M_impl ? _M_impl->_M_thread : native_handle(); } // Returns a value that hints at the number of hardware thread contexts. static unsigned int @@ -184,7 +205,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: void - _M_start_thread(__shared_base_type); + _M_start_thread(__compat_base_type); + + void + _M_start_thread2(__shared_base_type); template shared_ptr<_Impl<_Callable>> @@ -225,7 +249,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { size_t operator()(const thread::id& __id) const - { return std::_Hash_impl::hash(__id._M_thread); } + { return std::_Hash_impl::hash(__id._M_id); } }; template @@ -235,7 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__id == thread::id()) return __out << "thread::id of a non-executing thread"; else - return __out << __id._M_thread; + return __out << __id._M_id; } _GLIBCXX_END_NAMESPACE_VERSION @@ -249,8 +273,8 @@ _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION /// get_id - inline thread::id - get_id() { return thread::id(__gthread_self()); } + thread::id + get_id(); #ifdef _GLIBCXX_USE_SCHED_YIELD /// yield Index: src/thread.cc =================================================================== --- src/thread.cc (revision 171022) +++ src/thread.cc (working copy) @@ -32,12 +32,41 @@ namespace std _GLIBCXX_VISIBILITY(defaul { namespace { + const size_t main_thread_id = 1; + + inline size_t& get_per_thread_id() + { + static __thread size_t __this_id = main_thread_id; + return __this_id; + } + } + + namespace this_thread + { + _GLIBCXX_BEGIN_NAMESPACE_VERSION + struct __this_thread + { + static thread::id _S_get_id() + { return thread::id(get_per_thread_id()); } + + static void _S_set_id(thread::id __id) + { get_per_thread_id() = __id._M_id; } + }; + + thread::id get_id() { return __this_thread::_S_get_id(); } + + _GLIBCXX_END_NAMESPACE_VERSION + } + + namespace + { extern "C" void* execute_native_thread_routine(void* __p) { - thread::_Impl_base* __t = static_cast(__p); + thread::_Impl_base2* __t = static_cast(__p); thread::__shared_base_type __local; __local.swap(__t->_M_this_ptr); + this_thread::__this_thread::_S_set_id(__t->_M_id); __try { @@ -59,13 +88,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { int __e = EINVAL; - if (_M_id != id()) - __e = __gthread_join(_M_id._M_thread, 0); + if (_M_impl) + __e = __gthread_join(_M_impl->_M_thread, 0); if (__e) __throw_system_error(__e); - _M_id = id(); + _M_impl.reset(); } void @@ -73,29 +102,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { int __e = EINVAL; - if (_M_id != id()) - __e = __gthread_detach(_M_id._M_thread); + if (_M_impl) + __e = __gthread_detach(_M_impl->_M_thread); if (__e) __throw_system_error(__e); - _M_id = id(); + _M_impl.reset(); + } + + void + thread::_M_start_thread(__compat_base_type __b) + { + __throw_system_error(int(errc::operation_not_permitted)); } void - thread::_M_start_thread(__shared_base_type __b) + thread::_M_start_thread2(__shared_base_type __b) { if (!__gthread_active_p()) __throw_system_error(int(errc::operation_not_permitted)); + static size_t __last_thread = main_thread_id; + __b->_M_id = id(__sync_add_and_fetch(&__last_thread, 1)); + if (__b->_M_id == id()) + __throw_system_error(int(errc::resource_unavailable_try_again)); + __b->_M_this_ptr = __b; - int __e = __gthread_create(&_M_id._M_thread, + + int __e = __gthread_create(&__b->_M_thread, &execute_native_thread_routine, __b.get()); if (__e) { __b->_M_this_ptr.reset(); __throw_system_error(__e); } + _M_impl.swap(__b); } _GLIBCXX_END_NAMESPACE_VERSION