Index: stable/11/contrib/libc++/include/__threading_support =================================================================== --- stable/11/contrib/libc++/include/__threading_support (revision 351766) +++ stable/11/contrib/libc++/include/__threading_support (revision 351767) @@ -1,402 +1,483 @@ // -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_THREADING_SUPPORT #define _LIBCPP_THREADING_SUPPORT #include <__config> #include +#include #include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header #endif #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) # include <__external_threading> #elif !defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) # include # include #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_HAS_THREAD_API_WIN32) #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS #else #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY #endif #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) #else #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS #endif _LIBCPP_BEGIN_NAMESPACE_STD #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) // Mutex typedef pthread_mutex_t __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER typedef pthread_mutex_t __libcpp_recursive_mutex_t; // Condition Variable typedef pthread_cond_t __libcpp_condvar_t; #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER // Execute once typedef pthread_once_t __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT // Thread id typedef pthread_t __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef pthread_t __libcpp_thread_t; // Thread Local Storage typedef pthread_key_t __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC #else // Mutex typedef void* __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER 0 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) typedef void* __libcpp_recursive_mutex_t[6]; #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) typedef void* __libcpp_recursive_mutex_t[5]; #else # error Unsupported architecture #endif // Condition Variable typedef void* __libcpp_condvar_t; #define _LIBCPP_CONDVAR_INITIALIZER 0 // Execute Once typedef void* __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER 0 // Thread ID typedef long __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef void* __libcpp_thread_t; // Thread Local Storage typedef long __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall #endif // Mutex _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); // Condition variable _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, timespec *__ts); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); // Execute once _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)(void)); // Thread id _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); // Thread _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg); _LIBCPP_THREAD_ABI_VISIBILITY __libcpp_thread_id __libcpp_thread_get_current_id(); _LIBCPP_THREAD_ABI_VISIBILITY __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_join(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_detach(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_yield(); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); // Thread local storage _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); _LIBCPP_THREAD_ABI_VISIBILITY void *__libcpp_tls_get(__libcpp_tls_key __key); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ defined(_LIBCPP_HAS_THREAD_API_PTHREAD) int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { pthread_mutexattr_t attr; int __ec = pthread_mutexattr_init(&attr); if (__ec) return __ec; __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if (__ec) { pthread_mutexattr_destroy(&attr); return __ec; } __ec = pthread_mutex_init(__m, &attr); if (__ec) { pthread_mutexattr_destroy(&attr); return __ec; } __ec = pthread_mutexattr_destroy(&attr); if (__ec) { pthread_mutex_destroy(__m); return __ec; } return 0; } int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_lock(__m); } bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_trylock(__m) == 0; } int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) { return pthread_mutex_unlock(__m); } int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_destroy(__m); } int __libcpp_mutex_lock(__libcpp_mutex_t *__m) { return pthread_mutex_lock(__m); } bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) { return pthread_mutex_trylock(__m) == 0; } int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) { return pthread_mutex_unlock(__m); } int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) { return pthread_mutex_destroy(__m); } // Condition Variable int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) { return pthread_cond_signal(__cv); } int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) { return pthread_cond_broadcast(__cv); } int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) { return pthread_cond_wait(__cv, __m); } int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, timespec *__ts) { return pthread_cond_timedwait(__cv, __m, __ts); } int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) { return pthread_cond_destroy(__cv); } // Execute once int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)(void)) { return pthread_once(flag, init_routine); } // Thread id // Returns non-zero if the thread ids are equal, otherwise 0 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return pthread_equal(t1, t2) != 0; } // Returns non-zero if t1 < t2, otherwise 0 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; } // Thread bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { return *__t == 0; } int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg) { return pthread_create(__t, 0, __func, __arg); } __libcpp_thread_id __libcpp_thread_get_current_id() { return pthread_self(); } __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) { return *__t; } int __libcpp_thread_join(__libcpp_thread_t *__t) { return pthread_join(*__t, 0); } int __libcpp_thread_detach(__libcpp_thread_t *__t) { return pthread_detach(*__t); } void __libcpp_thread_yield() { sched_yield(); } void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { using namespace chrono; seconds __s = duration_cast(__ns); timespec __ts; typedef decltype(__ts.tv_sec) ts_sec; _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits::max(); if (__s.count() < __ts_sec_max) { __ts.tv_sec = static_cast(__s.count()); __ts.tv_nsec = static_cast((__ns - __s).count()); } else { __ts.tv_sec = __ts_sec_max; __ts.tv_nsec = 999999999; // (10^9 - 1) } while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); } // Thread local storage int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) { return pthread_key_create(__key, __at_exit); } void *__libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); } int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) { return pthread_setspecific(__key, __p); } #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL + +class _LIBCPP_TYPE_VIS thread; +class _LIBCPP_TYPE_VIS __thread_id; + +namespace this_thread +{ + +_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; + +} // this_thread + +template<> struct hash<__thread_id>; + +class _LIBCPP_TEMPLATE_VIS __thread_id +{ + // FIXME: pthread_t is a pointer on Darwin but a long on Linux. + // NULL is the no-thread value on Darwin. Someone needs to check + // on other platforms. We assume 0 works everywhere for now. + __libcpp_thread_id __id_; + +public: + _LIBCPP_INLINE_VISIBILITY + __thread_id() _NOEXCEPT : __id_(0) {} + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT + { // don't pass id==0 to underlying routines + if (__x.__id_ == 0) return __y.__id_ == 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_equal(__x.__id_, __y.__id_); + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__x == __y);} + friend _LIBCPP_INLINE_VISIBILITY + bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT + { // id==0 is always less than any other thread_id + if (__x.__id_ == 0) return __y.__id_ != 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_less(__x.__id_, __y.__id_); + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__y < __x);} + friend _LIBCPP_INLINE_VISIBILITY + bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT + {return __y < __x ;} + friend _LIBCPP_INLINE_VISIBILITY + bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__x < __y);} + + _LIBCPP_INLINE_VISIBILITY + void __reset() { __id_ = 0; } + + template + friend + _LIBCPP_INLINE_VISIBILITY + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); + +private: + _LIBCPP_INLINE_VISIBILITY + __thread_id(__libcpp_thread_id __id) : __id_(__id) {} + + friend __thread_id this_thread::get_id() _NOEXCEPT; + friend class _LIBCPP_TYPE_VIS thread; + friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; +}; + +namespace this_thread +{ + +inline _LIBCPP_INLINE_VISIBILITY +__thread_id +get_id() _NOEXCEPT +{ + return __libcpp_thread_get_current_id(); +} + +} // this_thread _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // !_LIBCPP_HAS_NO_THREADS #endif // _LIBCPP_THREADING_SUPPORT Index: stable/11/contrib/libc++/include/mutex =================================================================== --- stable/11/contrib/libc++/include/mutex (revision 351766) +++ stable/11/contrib/libc++/include/mutex (revision 351767) @@ -1,703 +1,703 @@ // -*- C++ -*- //===--------------------------- mutex ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_MUTEX #define _LIBCPP_MUTEX /* mutex synopsis namespace std { class mutex { public: constexpr mutex() noexcept; ~mutex(); mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; void lock(); bool try_lock(); void unlock(); typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle(); }; class recursive_mutex { public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock() noexcept; void unlock(); typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle(); }; class timed_mutex { public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); }; class recursive_timed_mutex { public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); bool try_lock() noexcept; template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); }; struct defer_lock_t {}; struct try_to_lock_t {}; struct adopt_lock_t {}; inline constexpr defer_lock_t defer_lock{}; inline constexpr try_to_lock_t try_to_lock{}; inline constexpr adopt_lock_t adopt_lock{}; template class lock_guard { public: typedef Mutex mutex_type; explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard(); lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; template class scoped_lock // C++17 { public: using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex explicit scoped_lock(MutexTypes&... m); scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock(); scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; private: tuple pm; // exposition only }; template class unique_lock { public: typedef Mutex mutex_type; unique_lock() noexcept; explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template unique_lock(mutex_type& m, const chrono::time_point& abs_time); template unique_lock(mutex_type& m, const chrono::duration& rel_time); ~unique_lock(); unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; unique_lock(unique_lock&& u) noexcept; unique_lock& operator=(unique_lock&& u) noexcept; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); void swap(unique_lock& u) noexcept; mutex_type* release() noexcept; bool owns_lock() const noexcept; explicit operator bool () const noexcept; mutex_type* mutex() const noexcept; }; template void swap(unique_lock& x, unique_lock& y) noexcept; template int try_lock(L1&, L2&, L3&...); template void lock(L1&, L2&, L3&...); struct once_flag { constexpr once_flag() noexcept; once_flag(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete; }; template void call_once(once_flag& flag, Callable&& func, Args&&... args); } // std */ #include <__config> #include <__mutex_base> #include #include #ifndef _LIBCPP_CXX03_LANG #include #endif #include #include <__threading_support> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS class _LIBCPP_TYPE_VIS recursive_mutex { __libcpp_recursive_mutex_t __m_; public: recursive_mutex(); ~recursive_mutex(); private: recursive_mutex(const recursive_mutex&); // = delete; recursive_mutex& operator=(const recursive_mutex&); // = delete; public: void lock(); bool try_lock() _NOEXCEPT; void unlock() _NOEXCEPT; typedef __libcpp_recursive_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; class _LIBCPP_TYPE_VIS timed_mutex { mutex __m_; condition_variable __cv_; bool __locked_; public: timed_mutex(); ~timed_mutex(); private: timed_mutex(const timed_mutex&); // = delete; timed_mutex& operator=(const timed_mutex&); // = delete; public: void lock(); bool try_lock() _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {return try_lock_until(chrono::steady_clock::now() + __d);} template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; template bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; unique_lock __lk(__m_); bool no_timeout = _Clock::now() < __t; while (no_timeout && __locked_) no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; if (!__locked_) { __locked_ = true; return true; } return false; } class _LIBCPP_TYPE_VIS recursive_timed_mutex { mutex __m_; condition_variable __cv_; size_t __count_; - __libcpp_thread_id __id_; + __thread_id __id_; public: recursive_timed_mutex(); ~recursive_timed_mutex(); private: recursive_timed_mutex(const recursive_timed_mutex&); // = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; public: void lock(); bool try_lock() _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {return try_lock_until(chrono::steady_clock::now() + __d);} template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; template bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; - __libcpp_thread_id __id = __libcpp_thread_get_current_id(); + __thread_id __id = this_thread::get_id(); unique_lock lk(__m_); - if (__libcpp_thread_id_equal(__id, __id_)) + if (__id == __id_) { if (__count_ == numeric_limits::max()) return false; ++__count_; return true; } bool no_timeout = _Clock::now() < __t; while (no_timeout && __count_ != 0) no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; if (__count_ == 0) { __count_ = 1; __id_ = __id; return true; } return false; } template int try_lock(_L0& __l0, _L1& __l1) { unique_lock<_L0> __u0(__l0, try_to_lock); if (__u0.owns_lock()) { if (__l1.try_lock()) { __u0.release(); return -1; } else return 1; } return 0; } #ifndef _LIBCPP_CXX03_LANG template int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { int __r = 0; unique_lock<_L0> __u0(__l0, try_to_lock); if (__u0.owns_lock()) { __r = try_lock(__l1, __l2, __l3...); if (__r == -1) __u0.release(); else ++__r; } return __r; } #endif // _LIBCPP_CXX03_LANG template void lock(_L0& __l0, _L1& __l1) { while (true) { { unique_lock<_L0> __u0(__l0); if (__l1.try_lock()) { __u0.release(); break; } } __libcpp_thread_yield(); { unique_lock<_L1> __u1(__l1); if (__l0.try_lock()) { __u1.release(); break; } } __libcpp_thread_yield(); } } #ifndef _LIBCPP_CXX03_LANG template void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) { while (true) { switch (__i) { case 0: { unique_lock<_L0> __u0(__l0); __i = try_lock(__l1, __l2, __l3...); if (__i == -1) { __u0.release(); return; } } ++__i; __libcpp_thread_yield(); break; case 1: { unique_lock<_L1> __u1(__l1); __i = try_lock(__l2, __l3..., __l0); if (__i == -1) { __u1.release(); return; } } if (__i == sizeof...(_L3) + 1) __i = 0; else __i += 2; __libcpp_thread_yield(); break; default: __lock_first(__i - 2, __l2, __l3..., __l0, __l1); return; } } } template inline _LIBCPP_INLINE_VISIBILITY void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) { __lock_first(0, __l0, __l1, __l2, __l3...); } template inline _LIBCPP_INLINE_VISIBILITY void __unlock(_L0& __l0) { __l0.unlock(); } template inline _LIBCPP_INLINE_VISIBILITY void __unlock(_L0& __l0, _L1& __l1) { __l0.unlock(); __l1.unlock(); } template inline _LIBCPP_INLINE_VISIBILITY void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { __l0.unlock(); __l1.unlock(); _VSTD::__unlock(__l2, __l3...); } #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 14 template class _LIBCPP_TEMPLATE_VIS scoped_lock; template <> class _LIBCPP_TEMPLATE_VIS scoped_lock<> { public: explicit scoped_lock() {} ~scoped_lock() = default; _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(adopt_lock_t) {} scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; }; template class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { public: typedef _Mutex mutex_type; private: mutex_type& __m_; public: explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) {__m_.lock();} ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; }; template class _LIBCPP_TEMPLATE_VIS scoped_lock { static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); typedef tuple<_MArgs&...> _MutexTuple; public: _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { _VSTD::lock(__margs...); } _LIBCPP_INLINE_VISIBILITY scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) { } _LIBCPP_INLINE_VISIBILITY ~scoped_lock() { typedef typename __make_tuple_indices::type _Indices; __unlock_unpack(_Indices{}, __t_); } scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; private: template _LIBCPP_INLINE_VISIBILITY static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); } _MutexTuple __t_; }; #endif // _LIBCPP_STD_VER > 14 #endif // !_LIBCPP_HAS_NO_THREADS struct _LIBCPP_TEMPLATE_VIS once_flag; #ifndef _LIBCPP_CXX03_LANG template _LIBCPP_INLINE_VISIBILITY void call_once(once_flag&, _Callable&&, _Args&&...); #else // _LIBCPP_CXX03_LANG template _LIBCPP_INLINE_VISIBILITY void call_once(once_flag&, _Callable&); template _LIBCPP_INLINE_VISIBILITY void call_once(once_flag&, const _Callable&); #endif // _LIBCPP_CXX03_LANG struct _LIBCPP_TEMPLATE_VIS once_flag { _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR once_flag() _NOEXCEPT : __state_(0) {} private: once_flag(const once_flag&); // = delete; once_flag& operator=(const once_flag&); // = delete; unsigned long __state_; #ifndef _LIBCPP_CXX03_LANG template friend void call_once(once_flag&, _Callable&&, _Args&&...); #else // _LIBCPP_CXX03_LANG template friend void call_once(once_flag&, _Callable&); template friend void call_once(once_flag&, const _Callable&); #endif // _LIBCPP_CXX03_LANG }; #ifndef _LIBCPP_CXX03_LANG template class __call_once_param { _Fp& __f_; public: _LIBCPP_INLINE_VISIBILITY explicit __call_once_param(_Fp& __f) : __f_(__f) {} _LIBCPP_INLINE_VISIBILITY void operator()() { typedef typename __make_tuple_indices::value, 1>::type _Index; __execute(_Index()); } private: template _LIBCPP_INLINE_VISIBILITY void __execute(__tuple_indices<_Indices...>) { __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); } }; #else template class __call_once_param { _Fp& __f_; public: _LIBCPP_INLINE_VISIBILITY explicit __call_once_param(_Fp& __f) : __f_(__f) {} _LIBCPP_INLINE_VISIBILITY void operator()() { __f_(); } }; #endif template void __call_once_proxy(void* __vp) { __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); (*__p)(); } _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*)); #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) { if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) { typedef tuple<_Callable&&, _Args&&...> _Gp; _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); __call_once_param<_Gp> __p(__f); __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); } } #else // _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void call_once(once_flag& __flag, _Callable& __func) { if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) { __call_once_param<_Callable> __p(__func); __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); } } template inline _LIBCPP_INLINE_VISIBILITY void call_once(once_flag& __flag, const _Callable& __func) { if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) { __call_once_param __p(__func); __call_once(__flag.__state_, &__p, &__call_once_proxy); } } #endif // _LIBCPP_CXX03_LANG _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // _LIBCPP_MUTEX Index: stable/11/contrib/libc++/include/thread =================================================================== --- stable/11/contrib/libc++/include/thread (revision 351766) +++ stable/11/contrib/libc++/include/thread (revision 351767) @@ -1,484 +1,420 @@ // -*- C++ -*- //===--------------------------- thread -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_THREAD #define _LIBCPP_THREAD /* thread synopsis #define __STDCPP_THREADS__ __cplusplus namespace std { class thread { public: class id; typedef pthread_t native_handle_type; thread() noexcept; template explicit thread(F&& f, Args&&... args); ~thread(); thread(const thread&) = delete; thread(thread&& t) noexcept; thread& operator=(const thread&) = delete; thread& operator=(thread&& t) noexcept; void swap(thread& t) noexcept; bool joinable() const noexcept; void join(); void detach(); id get_id() const noexcept; native_handle_type native_handle(); static unsigned hardware_concurrency() noexcept; }; void swap(thread& x, thread& y) noexcept; class thread::id { public: id() noexcept; }; bool operator==(thread::id x, thread::id y) noexcept; bool operator!=(thread::id x, thread::id y) noexcept; bool operator< (thread::id x, thread::id y) noexcept; bool operator<=(thread::id x, thread::id y) noexcept; bool operator> (thread::id x, thread::id y) noexcept; bool operator>=(thread::id x, thread::id y) noexcept; template basic_ostream& operator<<(basic_ostream& out, thread::id id); namespace this_thread { thread::id get_id() noexcept; void yield() noexcept; template void sleep_until(const chrono::time_point& abs_time); template void sleep_for(const chrono::duration& rel_time); } // this_thread } // std */ #include <__config> #include #include <__functional_base> #include #include #include #include #include #include #include <__mutex_base> #ifndef _LIBCPP_CXX03_LANG #include #endif #include <__threading_support> #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #define __STDCPP_THREADS__ __cplusplus #ifdef _LIBCPP_HAS_NO_THREADS #error is not supported on this single threaded system #else // !_LIBCPP_HAS_NO_THREADS _LIBCPP_BEGIN_NAMESPACE_STD template class __thread_specific_ptr; class _LIBCPP_TYPE_VIS __thread_struct; class _LIBCPP_HIDDEN __thread_struct_imp; class __assoc_sub_state; _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); class _LIBCPP_TYPE_VIS __thread_struct { __thread_struct_imp* __p_; __thread_struct(const __thread_struct&); __thread_struct& operator=(const __thread_struct&); public: __thread_struct(); ~__thread_struct(); void notify_all_at_thread_exit(condition_variable*, mutex*); void __make_ready_at_thread_exit(__assoc_sub_state*); }; template class __thread_specific_ptr { __libcpp_tls_key __key_; // Only __thread_local_data() may construct a __thread_specific_ptr // and only with _Tp == __thread_struct. static_assert((is_same<_Tp, __thread_struct>::value), ""); __thread_specific_ptr(); friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); __thread_specific_ptr(const __thread_specific_ptr&); __thread_specific_ptr& operator=(const __thread_specific_ptr&); _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); public: typedef _Tp* pointer; ~__thread_specific_ptr(); _LIBCPP_INLINE_VISIBILITY pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} _LIBCPP_INLINE_VISIBILITY pointer operator*() const {return *get();} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return get();} void set_pointer(pointer __p); }; template void _LIBCPP_TLS_DESTRUCTOR_CC __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) { delete static_cast(__p); } template __thread_specific_ptr<_Tp>::__thread_specific_ptr() { int __ec = __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); if (__ec) __throw_system_error(__ec, "__thread_specific_ptr construction failed"); } template __thread_specific_ptr<_Tp>::~__thread_specific_ptr() { // __thread_specific_ptr is only created with a static storage duration // so this destructor is only invoked during program termination. Invoking // pthread_key_delete(__key_) may prevent other threads from deleting their // thread local data. For this reason we leak the key. } template void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) { _LIBCPP_ASSERT(get() == nullptr, "Attempting to overwrite thread local data"); __libcpp_tls_set(__key_, __p); } -class _LIBCPP_TYPE_VIS thread; -class _LIBCPP_TYPE_VIS __thread_id; - -namespace this_thread -{ - -_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; - -} // this_thread - -template<> struct hash<__thread_id>; - -class _LIBCPP_TEMPLATE_VIS __thread_id -{ - // FIXME: pthread_t is a pointer on Darwin but a long on Linux. - // NULL is the no-thread value on Darwin. Someone needs to check - // on other platforms. We assume 0 works everywhere for now. - __libcpp_thread_id __id_; - -public: - _LIBCPP_INLINE_VISIBILITY - __thread_id() _NOEXCEPT : __id_(0) {} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - {return __libcpp_thread_id_equal(__x.__id_, __y.__id_);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x == __y);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __libcpp_thread_id_less(__x.__id_, __y.__id_);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__y < __x);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __y < __x ;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x < __y);} - - template - friend - _LIBCPP_INLINE_VISIBILITY - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) - {return __os << __id.__id_;} - -private: - _LIBCPP_INLINE_VISIBILITY - __thread_id(__libcpp_thread_id __id) : __id_(__id) {} - - friend __thread_id this_thread::get_id() _NOEXCEPT; - friend class _LIBCPP_TYPE_VIS thread; - friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; -}; - template<> struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> : public unary_function<__thread_id, size_t> { _LIBCPP_INLINE_VISIBILITY size_t operator()(__thread_id __v) const _NOEXCEPT { return hash<__libcpp_thread_id>()(__v.__id_); } }; -namespace this_thread -{ - -inline _LIBCPP_INLINE_VISIBILITY -__thread_id -get_id() _NOEXCEPT -{ - return __libcpp_thread_get_current_id(); -} - -} // this_thread +template +_LIBCPP_INLINE_VISIBILITY +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) +{return __os << __id.__id_;} class _LIBCPP_TYPE_VIS thread { __libcpp_thread_t __t_; thread(const thread&); thread& operator=(const thread&); public: typedef __thread_id id; typedef __libcpp_thread_t native_handle_type; _LIBCPP_INLINE_VISIBILITY thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} #ifndef _LIBCPP_CXX03_LANG template ::type, thread>::value >::type > _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp&& __f, _Args&&... __args); #else // _LIBCPP_CXX03_LANG template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f); #endif ~thread(); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;} _LIBCPP_INLINE_VISIBILITY thread& operator=(thread&& __t) _NOEXCEPT; #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} _LIBCPP_INLINE_VISIBILITY bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} void join(); void detach(); _LIBCPP_INLINE_VISIBILITY id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() _NOEXCEPT {return __t_;} static unsigned hardware_concurrency() _NOEXCEPT; }; #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) { __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); } template void* __thread_proxy(void* __vp) { // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...> std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release()); typedef typename __make_tuple_indices::value, 2>::type _Index; __thread_execute(*__p, _Index()); return nullptr; } template thread::thread(_Fp&& __f, _Args&&... __args) { typedef unique_ptr<__thread_struct> _TSPtr; _TSPtr __tsp(new __thread_struct); typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; _VSTD::unique_ptr<_Gp> __p( new _Gp(std::move(__tsp), __decay_copy(_VSTD::forward<_Fp>(__f)), __decay_copy(_VSTD::forward<_Args>(__args))...)); int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); if (__ec == 0) __p.release(); else __throw_system_error(__ec, "thread constructor failed"); } inline thread& thread::operator=(thread&& __t) _NOEXCEPT { if (!__libcpp_thread_isnull(&__t_)) terminate(); __t_ = __t.__t_; __t.__t_ = _LIBCPP_NULL_THREAD; return *this; } #else // _LIBCPP_CXX03_LANG template struct __thread_invoke_pair { // This type is used to pass memory for thread local storage and a functor // to a newly created thread because std::pair doesn't work with // std::unique_ptr in C++03. __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} unique_ptr<__thread_struct> __tsp_; _Fp __fn_; }; template void* __thread_proxy_cxx03(void* __vp) { std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); __thread_local_data().set_pointer(__p->__tsp_.release()); (__p->__fn_)(); return nullptr; } template thread::thread(_Fp __f) { typedef __thread_invoke_pair<_Fp> _InvokePair; typedef std::unique_ptr<_InvokePair> _PairPtr; _PairPtr __pp(new _InvokePair(__f)); int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); if (__ec == 0) __pp.release(); else __throw_system_error(__ec, "thread constructor failed"); } #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_INLINE_VISIBILITY void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} namespace this_thread { _LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); template void sleep_for(const chrono::duration<_Rep, _Period>& __d) { using namespace chrono; if (__d > duration<_Rep, _Period>::zero()) { _LIBCPP_CONSTEXPR duration _Max = nanoseconds::max(); nanoseconds __ns; if (__d < _Max) { __ns = duration_cast(__d); if (__ns < __d) ++__ns; } else __ns = nanoseconds::max(); sleep_for(__ns); } } template void sleep_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; mutex __mut; condition_variable __cv; unique_lock __lk(__mut); while (_Clock::now() < __t) __cv.wait_until(__lk, __t); } template inline _LIBCPP_INLINE_VISIBILITY void sleep_until(const chrono::time_point& __t) { using namespace chrono; sleep_for(__t - steady_clock::now()); } inline _LIBCPP_INLINE_VISIBILITY void yield() _NOEXCEPT {__libcpp_thread_yield();} } // this_thread _LIBCPP_END_NAMESPACE_STD #endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_POP_MACROS #endif // _LIBCPP_THREAD Index: stable/11/contrib/libc++/src/mutex.cpp =================================================================== --- stable/11/contrib/libc++/src/mutex.cpp (revision 351766) +++ stable/11/contrib/libc++/src/mutex.cpp (revision 351767) @@ -1,258 +1,258 @@ //===------------------------- mutex.cpp ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "mutex" #include "limits" #include "system_error" #include "include/atomic_support.h" #include "__undef_macros" _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS const defer_lock_t defer_lock = {}; const try_to_lock_t try_to_lock = {}; const adopt_lock_t adopt_lock = {}; mutex::~mutex() { __libcpp_mutex_destroy(&__m_); } void mutex::lock() { int ec = __libcpp_mutex_lock(&__m_); if (ec) __throw_system_error(ec, "mutex lock failed"); } bool mutex::try_lock() _NOEXCEPT { return __libcpp_mutex_trylock(&__m_); } void mutex::unlock() _NOEXCEPT { int ec = __libcpp_mutex_unlock(&__m_); (void)ec; _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed"); } // recursive_mutex recursive_mutex::recursive_mutex() { int ec = __libcpp_recursive_mutex_init(&__m_); if (ec) __throw_system_error(ec, "recursive_mutex constructor failed"); } recursive_mutex::~recursive_mutex() { int e = __libcpp_recursive_mutex_destroy(&__m_); (void)e; _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed"); } void recursive_mutex::lock() { int ec = __libcpp_recursive_mutex_lock(&__m_); if (ec) __throw_system_error(ec, "recursive_mutex lock failed"); } void recursive_mutex::unlock() _NOEXCEPT { int e = __libcpp_recursive_mutex_unlock(&__m_); (void)e; _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed"); } bool recursive_mutex::try_lock() _NOEXCEPT { return __libcpp_recursive_mutex_trylock(&__m_); } // timed_mutex timed_mutex::timed_mutex() : __locked_(false) { } timed_mutex::~timed_mutex() { lock_guard _(__m_); } void timed_mutex::lock() { unique_lock lk(__m_); while (__locked_) __cv_.wait(lk); __locked_ = true; } bool timed_mutex::try_lock() _NOEXCEPT { unique_lock lk(__m_, try_to_lock); if (lk.owns_lock() && !__locked_) { __locked_ = true; return true; } return false; } void timed_mutex::unlock() _NOEXCEPT { lock_guard _(__m_); __locked_ = false; __cv_.notify_one(); } // recursive_timed_mutex recursive_timed_mutex::recursive_timed_mutex() : __count_(0), - __id_(0) + __id_{} { } recursive_timed_mutex::~recursive_timed_mutex() { lock_guard _(__m_); } void recursive_timed_mutex::lock() { - __libcpp_thread_id id = __libcpp_thread_get_current_id(); + __thread_id id = this_thread::get_id(); unique_lock lk(__m_); - if (__libcpp_thread_id_equal(id, __id_)) + if (id ==__id_) { if (__count_ == numeric_limits::max()) __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); ++__count_; return; } while (__count_ != 0) __cv_.wait(lk); __count_ = 1; __id_ = id; } bool recursive_timed_mutex::try_lock() _NOEXCEPT { - __libcpp_thread_id id = __libcpp_thread_get_current_id(); + __thread_id id = this_thread::get_id(); unique_lock lk(__m_, try_to_lock); - if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_))) + if (lk.owns_lock() && (__count_ == 0 || id == __id_)) { if (__count_ == numeric_limits::max()) return false; ++__count_; __id_ = id; return true; } return false; } void recursive_timed_mutex::unlock() _NOEXCEPT { unique_lock lk(__m_); if (--__count_ == 0) { - __id_ = 0; + __id_.__reset(); lk.unlock(); __cv_.notify_one(); } } #endif // !_LIBCPP_HAS_NO_THREADS // If dispatch_once_f ever handles C++ exceptions, and if one can get to it // without illegal macros (unexpected macros not beginning with _UpperCase or // __lowercase), and if it stops spinning waiting threads, then call_once should // call into dispatch_once_f instead of here. Relevant radar this code needs to // keep in sync with: 7741191. #ifndef _LIBCPP_HAS_NO_THREADS _LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; _LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; #endif void __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) { #if defined(_LIBCPP_HAS_NO_THREADS) if (flag == 0) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS flag = 1; func(arg); flag = ~0ul; #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { flag = 0ul; throw; } #endif // _LIBCPP_NO_EXCEPTIONS } #else // !_LIBCPP_HAS_NO_THREADS __libcpp_mutex_lock(&mut); while (flag == 1) __libcpp_condvar_wait(&cv, &mut); if (flag == 0) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS __libcpp_relaxed_store(&flag, 1ul); __libcpp_mutex_unlock(&mut); func(arg); __libcpp_mutex_lock(&mut); __libcpp_atomic_store(&flag, ~0ul, _AO_Release); __libcpp_mutex_unlock(&mut); __libcpp_condvar_broadcast(&cv); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { __libcpp_mutex_lock(&mut); __libcpp_relaxed_store(&flag, 0ul); __libcpp_mutex_unlock(&mut); __libcpp_condvar_broadcast(&cv); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } else __libcpp_mutex_unlock(&mut); #endif // !_LIBCPP_HAS_NO_THREADS } _LIBCPP_END_NAMESPACE_STD Index: stable/11 =================================================================== --- stable/11 (revision 351766) +++ stable/11 (revision 351767) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r351253 Index: stable/12/contrib/libc++/include/__threading_support =================================================================== --- stable/12/contrib/libc++/include/__threading_support (revision 351766) +++ stable/12/contrib/libc++/include/__threading_support (revision 351767) @@ -1,402 +1,483 @@ // -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_THREADING_SUPPORT #define _LIBCPP_THREADING_SUPPORT #include <__config> #include +#include #include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header #endif #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) # include <__external_threading> #elif !defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) # include # include #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_HAS_THREAD_API_WIN32) #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS #else #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY #endif #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) #else #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS #endif _LIBCPP_BEGIN_NAMESPACE_STD #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) // Mutex typedef pthread_mutex_t __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER typedef pthread_mutex_t __libcpp_recursive_mutex_t; // Condition Variable typedef pthread_cond_t __libcpp_condvar_t; #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER // Execute once typedef pthread_once_t __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT // Thread id typedef pthread_t __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef pthread_t __libcpp_thread_t; // Thread Local Storage typedef pthread_key_t __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC #else // Mutex typedef void* __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER 0 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) typedef void* __libcpp_recursive_mutex_t[6]; #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) typedef void* __libcpp_recursive_mutex_t[5]; #else # error Unsupported architecture #endif // Condition Variable typedef void* __libcpp_condvar_t; #define _LIBCPP_CONDVAR_INITIALIZER 0 // Execute Once typedef void* __libcpp_exec_once_flag; #define _LIBCPP_EXEC_ONCE_INITIALIZER 0 // Thread ID typedef long __libcpp_thread_id; // Thread #define _LIBCPP_NULL_THREAD 0U typedef void* __libcpp_thread_t; // Thread Local Storage typedef long __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall #endif // Mutex _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); // Condition variable _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, timespec *__ts); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); // Execute once _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)(void)); // Thread id _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); // Thread _LIBCPP_THREAD_ABI_VISIBILITY bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg); _LIBCPP_THREAD_ABI_VISIBILITY __libcpp_thread_id __libcpp_thread_get_current_id(); _LIBCPP_THREAD_ABI_VISIBILITY __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_join(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_thread_detach(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_yield(); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); // Thread local storage _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); _LIBCPP_THREAD_ABI_VISIBILITY void *__libcpp_tls_get(__libcpp_tls_key __key); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ defined(_LIBCPP_HAS_THREAD_API_PTHREAD) int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { pthread_mutexattr_t attr; int __ec = pthread_mutexattr_init(&attr); if (__ec) return __ec; __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if (__ec) { pthread_mutexattr_destroy(&attr); return __ec; } __ec = pthread_mutex_init(__m, &attr); if (__ec) { pthread_mutexattr_destroy(&attr); return __ec; } __ec = pthread_mutexattr_destroy(&attr); if (__ec) { pthread_mutex_destroy(__m); return __ec; } return 0; } int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_lock(__m); } bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_trylock(__m) == 0; } int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) { return pthread_mutex_unlock(__m); } int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) { return pthread_mutex_destroy(__m); } int __libcpp_mutex_lock(__libcpp_mutex_t *__m) { return pthread_mutex_lock(__m); } bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) { return pthread_mutex_trylock(__m) == 0; } int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) { return pthread_mutex_unlock(__m); } int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) { return pthread_mutex_destroy(__m); } // Condition Variable int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) { return pthread_cond_signal(__cv); } int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) { return pthread_cond_broadcast(__cv); } int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) { return pthread_cond_wait(__cv, __m); } int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, timespec *__ts) { return pthread_cond_timedwait(__cv, __m, __ts); } int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) { return pthread_cond_destroy(__cv); } // Execute once int __libcpp_execute_once(__libcpp_exec_once_flag *flag, void (*init_routine)(void)) { return pthread_once(flag, init_routine); } // Thread id // Returns non-zero if the thread ids are equal, otherwise 0 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) { return pthread_equal(t1, t2) != 0; } // Returns non-zero if t1 < t2, otherwise 0 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) { return t1 < t2; } // Thread bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { return *__t == 0; } int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), void *__arg) { return pthread_create(__t, 0, __func, __arg); } __libcpp_thread_id __libcpp_thread_get_current_id() { return pthread_self(); } __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) { return *__t; } int __libcpp_thread_join(__libcpp_thread_t *__t) { return pthread_join(*__t, 0); } int __libcpp_thread_detach(__libcpp_thread_t *__t) { return pthread_detach(*__t); } void __libcpp_thread_yield() { sched_yield(); } void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { using namespace chrono; seconds __s = duration_cast(__ns); timespec __ts; typedef decltype(__ts.tv_sec) ts_sec; _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits::max(); if (__s.count() < __ts_sec_max) { __ts.tv_sec = static_cast(__s.count()); __ts.tv_nsec = static_cast((__ns - __s).count()); } else { __ts.tv_sec = __ts_sec_max; __ts.tv_nsec = 999999999; // (10^9 - 1) } while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); } // Thread local storage int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) { return pthread_key_create(__key, __at_exit); } void *__libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); } int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) { return pthread_setspecific(__key, __p); } #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL + +class _LIBCPP_TYPE_VIS thread; +class _LIBCPP_TYPE_VIS __thread_id; + +namespace this_thread +{ + +_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; + +} // this_thread + +template<> struct hash<__thread_id>; + +class _LIBCPP_TEMPLATE_VIS __thread_id +{ + // FIXME: pthread_t is a pointer on Darwin but a long on Linux. + // NULL is the no-thread value on Darwin. Someone needs to check + // on other platforms. We assume 0 works everywhere for now. + __libcpp_thread_id __id_; + +public: + _LIBCPP_INLINE_VISIBILITY + __thread_id() _NOEXCEPT : __id_(0) {} + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT + { // don't pass id==0 to underlying routines + if (__x.__id_ == 0) return __y.__id_ == 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_equal(__x.__id_, __y.__id_); + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__x == __y);} + friend _LIBCPP_INLINE_VISIBILITY + bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT + { // id==0 is always less than any other thread_id + if (__x.__id_ == 0) return __y.__id_ != 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_less(__x.__id_, __y.__id_); + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__y < __x);} + friend _LIBCPP_INLINE_VISIBILITY + bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT + {return __y < __x ;} + friend _LIBCPP_INLINE_VISIBILITY + bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__x < __y);} + + _LIBCPP_INLINE_VISIBILITY + void __reset() { __id_ = 0; } + + template + friend + _LIBCPP_INLINE_VISIBILITY + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); + +private: + _LIBCPP_INLINE_VISIBILITY + __thread_id(__libcpp_thread_id __id) : __id_(__id) {} + + friend __thread_id this_thread::get_id() _NOEXCEPT; + friend class _LIBCPP_TYPE_VIS thread; + friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; +}; + +namespace this_thread +{ + +inline _LIBCPP_INLINE_VISIBILITY +__thread_id +get_id() _NOEXCEPT +{ + return __libcpp_thread_get_current_id(); +} + +} // this_thread _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // !_LIBCPP_HAS_NO_THREADS #endif // _LIBCPP_THREADING_SUPPORT Index: stable/12/contrib/libc++/include/mutex =================================================================== --- stable/12/contrib/libc++/include/mutex (revision 351766) +++ stable/12/contrib/libc++/include/mutex (revision 351767) @@ -1,703 +1,703 @@ // -*- C++ -*- //===--------------------------- mutex ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_MUTEX #define _LIBCPP_MUTEX /* mutex synopsis namespace std { class mutex { public: constexpr mutex() noexcept; ~mutex(); mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; void lock(); bool try_lock(); void unlock(); typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle(); }; class recursive_mutex { public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock() noexcept; void unlock(); typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle(); }; class timed_mutex { public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); }; class recursive_timed_mutex { public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); bool try_lock() noexcept; template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); }; struct defer_lock_t {}; struct try_to_lock_t {}; struct adopt_lock_t {}; inline constexpr defer_lock_t defer_lock{}; inline constexpr try_to_lock_t try_to_lock{}; inline constexpr adopt_lock_t adopt_lock{}; template class lock_guard { public: typedef Mutex mutex_type; explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard(); lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; template class scoped_lock // C++17 { public: using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex explicit scoped_lock(MutexTypes&... m); scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock(); scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; private: tuple pm; // exposition only }; template class unique_lock { public: typedef Mutex mutex_type; unique_lock() noexcept; explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template unique_lock(mutex_type& m, const chrono::time_point& abs_time); template unique_lock(mutex_type& m, const chrono::duration& rel_time); ~unique_lock(); unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; unique_lock(unique_lock&& u) noexcept; unique_lock& operator=(unique_lock&& u) noexcept; void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration& rel_time); template bool try_lock_until(const chrono::time_point& abs_time); void unlock(); void swap(unique_lock& u) noexcept; mutex_type* release() noexcept; bool owns_lock() const noexcept; explicit operator bool () const noexcept; mutex_type* mutex() const noexcept; }; template void swap(unique_lock& x, unique_lock& y) noexcept; template int try_lock(L1&, L2&, L3&...); template void lock(L1&, L2&, L3&...); struct once_flag { constexpr once_flag() noexcept; once_flag(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete; }; template void call_once(once_flag& flag, Callable&& func, Args&&... args); } // std */ #include <__config> #include <__mutex_base> #include #include #ifndef _LIBCPP_CXX03_LANG #include #endif #include #include <__threading_support> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS class _LIBCPP_TYPE_VIS recursive_mutex { __libcpp_recursive_mutex_t __m_; public: recursive_mutex(); ~recursive_mutex(); private: recursive_mutex(const recursive_mutex&); // = delete; recursive_mutex& operator=(const recursive_mutex&); // = delete; public: void lock(); bool try_lock() _NOEXCEPT; void unlock() _NOEXCEPT; typedef __libcpp_recursive_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; class _LIBCPP_TYPE_VIS timed_mutex { mutex __m_; condition_variable __cv_; bool __locked_; public: timed_mutex(); ~timed_mutex(); private: timed_mutex(const timed_mutex&); // = delete; timed_mutex& operator=(const timed_mutex&); // = delete; public: void lock(); bool try_lock() _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {return try_lock_until(chrono::steady_clock::now() + __d);} template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; template bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; unique_lock __lk(__m_); bool no_timeout = _Clock::now() < __t; while (no_timeout && __locked_) no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; if (!__locked_) { __locked_ = true; return true; } return false; } class _LIBCPP_TYPE_VIS recursive_timed_mutex { mutex __m_; condition_variable __cv_; size_t __count_; - __libcpp_thread_id __id_; + __thread_id __id_; public: recursive_timed_mutex(); ~recursive_timed_mutex(); private: recursive_timed_mutex(const recursive_timed_mutex&); // = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; public: void lock(); bool try_lock() _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {return try_lock_until(chrono::steady_clock::now() + __d);} template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock() _NOEXCEPT; }; template bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; - __libcpp_thread_id __id = __libcpp_thread_get_current_id(); + __thread_id __id = this_thread::get_id(); unique_lock lk(__m_); - if (__libcpp_thread_id_equal(__id, __id_)) + if (__id == __id_) { if (__count_ == numeric_limits::max()) return false; ++__count_; return true; } bool no_timeout = _Clock::now() < __t; while (no_timeout && __count_ != 0) no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; if (__count_ == 0) { __count_ = 1; __id_ = __id; return true; } return false; } template int try_lock(_L0& __l0, _L1& __l1) { unique_lock<_L0> __u0(__l0, try_to_lock); if (__u0.owns_lock()) { if (__l1.try_lock()) { __u0.release(); return -1; } else return 1; } return 0; } #ifndef _LIBCPP_CXX03_LANG template int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { int __r = 0; unique_lock<_L0> __u0(__l0, try_to_lock); if (__u0.owns_lock()) { __r = try_lock(__l1, __l2, __l3...); if (__r == -1) __u0.release(); else ++__r; } return __r; } #endif // _LIBCPP_CXX03_LANG template void lock(_L0& __l0, _L1& __l1) { while (true) { { unique_lock<_L0> __u0(__l0); if (__l1.try_lock()) { __u0.release(); break; } } __libcpp_thread_yield(); { unique_lock<_L1> __u1(__l1); if (__l0.try_lock()) { __u1.release(); break; } } __libcpp_thread_yield(); } } #ifndef _LIBCPP_CXX03_LANG template void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) { while (true) { switch (__i) { case 0: { unique_lock<_L0> __u0(__l0); __i = try_lock(__l1, __l2, __l3...); if (__i == -1) { __u0.release(); return; } } ++__i; __libcpp_thread_yield(); break; case 1: { unique_lock<_L1> __u1(__l1); __i = try_lock(__l2, __l3..., __l0); if (__i == -1) { __u1.release(); return; } } if (__i == sizeof...(_L3) + 1) __i = 0; else __i += 2; __libcpp_thread_yield(); break; default: __lock_first(__i - 2, __l2, __l3..., __l0, __l1); return; } } } template inline _LIBCPP_INLINE_VISIBILITY void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) { __lock_first(0, __l0, __l1, __l2, __l3...); } template inline _LIBCPP_INLINE_VISIBILITY void __unlock(_L0& __l0) { __l0.unlock(); } template inline _LIBCPP_INLINE_VISIBILITY void __unlock(_L0& __l0, _L1& __l1) { __l0.unlock(); __l1.unlock(); } template inline _LIBCPP_INLINE_VISIBILITY void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { __l0.unlock(); __l1.unlock(); _VSTD::__unlock(__l2, __l3...); } #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 14 template class _LIBCPP_TEMPLATE_VIS scoped_lock; template <> class _LIBCPP_TEMPLATE_VIS scoped_lock<> { public: explicit scoped_lock() {} ~scoped_lock() = default; _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(adopt_lock_t) {} scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; }; template class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { public: typedef _Mutex mutex_type; private: mutex_type& __m_; public: explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) {__m_.lock();} ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; }; template class _LIBCPP_TEMPLATE_VIS scoped_lock { static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); typedef tuple<_MArgs&...> _MutexTuple; public: _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { _VSTD::lock(__margs...); } _LIBCPP_INLINE_VISIBILITY scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) { } _LIBCPP_INLINE_VISIBILITY ~scoped_lock() { typedef typename __make_tuple_indices::type _Indices; __unlock_unpack(_Indices{}, __t_); } scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; private: template _LIBCPP_INLINE_VISIBILITY static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); } _MutexTuple __t_; }; #endif // _LIBCPP_STD_VER > 14 #endif // !_LIBCPP_HAS_NO_THREADS struct _LIBCPP_TEMPLATE_VIS once_flag; #ifndef _LIBCPP_CXX03_LANG template _LIBCPP_INLINE_VISIBILITY void call_once(once_flag&, _Callable&&, _Args&&...); #else // _LIBCPP_CXX03_LANG template _LIBCPP_INLINE_VISIBILITY void call_once(once_flag&, _Callable&); template _LIBCPP_INLINE_VISIBILITY void call_once(once_flag&, const _Callable&); #endif // _LIBCPP_CXX03_LANG struct _LIBCPP_TEMPLATE_VIS once_flag { _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR once_flag() _NOEXCEPT : __state_(0) {} private: once_flag(const once_flag&); // = delete; once_flag& operator=(const once_flag&); // = delete; unsigned long __state_; #ifndef _LIBCPP_CXX03_LANG template friend void call_once(once_flag&, _Callable&&, _Args&&...); #else // _LIBCPP_CXX03_LANG template friend void call_once(once_flag&, _Callable&); template friend void call_once(once_flag&, const _Callable&); #endif // _LIBCPP_CXX03_LANG }; #ifndef _LIBCPP_CXX03_LANG template class __call_once_param { _Fp& __f_; public: _LIBCPP_INLINE_VISIBILITY explicit __call_once_param(_Fp& __f) : __f_(__f) {} _LIBCPP_INLINE_VISIBILITY void operator()() { typedef typename __make_tuple_indices::value, 1>::type _Index; __execute(_Index()); } private: template _LIBCPP_INLINE_VISIBILITY void __execute(__tuple_indices<_Indices...>) { __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); } }; #else template class __call_once_param { _Fp& __f_; public: _LIBCPP_INLINE_VISIBILITY explicit __call_once_param(_Fp& __f) : __f_(__f) {} _LIBCPP_INLINE_VISIBILITY void operator()() { __f_(); } }; #endif template void __call_once_proxy(void* __vp) { __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); (*__p)(); } _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*)); #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) { if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) { typedef tuple<_Callable&&, _Args&&...> _Gp; _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); __call_once_param<_Gp> __p(__f); __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); } } #else // _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void call_once(once_flag& __flag, _Callable& __func) { if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) { __call_once_param<_Callable> __p(__func); __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); } } template inline _LIBCPP_INLINE_VISIBILITY void call_once(once_flag& __flag, const _Callable& __func) { if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) { __call_once_param __p(__func); __call_once(__flag.__state_, &__p, &__call_once_proxy); } } #endif // _LIBCPP_CXX03_LANG _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // _LIBCPP_MUTEX Index: stable/12/contrib/libc++/include/thread =================================================================== --- stable/12/contrib/libc++/include/thread (revision 351766) +++ stable/12/contrib/libc++/include/thread (revision 351767) @@ -1,484 +1,420 @@ // -*- C++ -*- //===--------------------------- thread -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_THREAD #define _LIBCPP_THREAD /* thread synopsis #define __STDCPP_THREADS__ __cplusplus namespace std { class thread { public: class id; typedef pthread_t native_handle_type; thread() noexcept; template explicit thread(F&& f, Args&&... args); ~thread(); thread(const thread&) = delete; thread(thread&& t) noexcept; thread& operator=(const thread&) = delete; thread& operator=(thread&& t) noexcept; void swap(thread& t) noexcept; bool joinable() const noexcept; void join(); void detach(); id get_id() const noexcept; native_handle_type native_handle(); static unsigned hardware_concurrency() noexcept; }; void swap(thread& x, thread& y) noexcept; class thread::id { public: id() noexcept; }; bool operator==(thread::id x, thread::id y) noexcept; bool operator!=(thread::id x, thread::id y) noexcept; bool operator< (thread::id x, thread::id y) noexcept; bool operator<=(thread::id x, thread::id y) noexcept; bool operator> (thread::id x, thread::id y) noexcept; bool operator>=(thread::id x, thread::id y) noexcept; template basic_ostream& operator<<(basic_ostream& out, thread::id id); namespace this_thread { thread::id get_id() noexcept; void yield() noexcept; template void sleep_until(const chrono::time_point& abs_time); template void sleep_for(const chrono::duration& rel_time); } // this_thread } // std */ #include <__config> #include #include <__functional_base> #include #include #include #include #include #include #include <__mutex_base> #ifndef _LIBCPP_CXX03_LANG #include #endif #include <__threading_support> #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #define __STDCPP_THREADS__ __cplusplus #ifdef _LIBCPP_HAS_NO_THREADS #error is not supported on this single threaded system #else // !_LIBCPP_HAS_NO_THREADS _LIBCPP_BEGIN_NAMESPACE_STD template class __thread_specific_ptr; class _LIBCPP_TYPE_VIS __thread_struct; class _LIBCPP_HIDDEN __thread_struct_imp; class __assoc_sub_state; _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); class _LIBCPP_TYPE_VIS __thread_struct { __thread_struct_imp* __p_; __thread_struct(const __thread_struct&); __thread_struct& operator=(const __thread_struct&); public: __thread_struct(); ~__thread_struct(); void notify_all_at_thread_exit(condition_variable*, mutex*); void __make_ready_at_thread_exit(__assoc_sub_state*); }; template class __thread_specific_ptr { __libcpp_tls_key __key_; // Only __thread_local_data() may construct a __thread_specific_ptr // and only with _Tp == __thread_struct. static_assert((is_same<_Tp, __thread_struct>::value), ""); __thread_specific_ptr(); friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); __thread_specific_ptr(const __thread_specific_ptr&); __thread_specific_ptr& operator=(const __thread_specific_ptr&); _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); public: typedef _Tp* pointer; ~__thread_specific_ptr(); _LIBCPP_INLINE_VISIBILITY pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} _LIBCPP_INLINE_VISIBILITY pointer operator*() const {return *get();} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return get();} void set_pointer(pointer __p); }; template void _LIBCPP_TLS_DESTRUCTOR_CC __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) { delete static_cast(__p); } template __thread_specific_ptr<_Tp>::__thread_specific_ptr() { int __ec = __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); if (__ec) __throw_system_error(__ec, "__thread_specific_ptr construction failed"); } template __thread_specific_ptr<_Tp>::~__thread_specific_ptr() { // __thread_specific_ptr is only created with a static storage duration // so this destructor is only invoked during program termination. Invoking // pthread_key_delete(__key_) may prevent other threads from deleting their // thread local data. For this reason we leak the key. } template void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) { _LIBCPP_ASSERT(get() == nullptr, "Attempting to overwrite thread local data"); __libcpp_tls_set(__key_, __p); } -class _LIBCPP_TYPE_VIS thread; -class _LIBCPP_TYPE_VIS __thread_id; - -namespace this_thread -{ - -_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; - -} // this_thread - -template<> struct hash<__thread_id>; - -class _LIBCPP_TEMPLATE_VIS __thread_id -{ - // FIXME: pthread_t is a pointer on Darwin but a long on Linux. - // NULL is the no-thread value on Darwin. Someone needs to check - // on other platforms. We assume 0 works everywhere for now. - __libcpp_thread_id __id_; - -public: - _LIBCPP_INLINE_VISIBILITY - __thread_id() _NOEXCEPT : __id_(0) {} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - {return __libcpp_thread_id_equal(__x.__id_, __y.__id_);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x == __y);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __libcpp_thread_id_less(__x.__id_, __y.__id_);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__y < __x);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __y < __x ;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x < __y);} - - template - friend - _LIBCPP_INLINE_VISIBILITY - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) - {return __os << __id.__id_;} - -private: - _LIBCPP_INLINE_VISIBILITY - __thread_id(__libcpp_thread_id __id) : __id_(__id) {} - - friend __thread_id this_thread::get_id() _NOEXCEPT; - friend class _LIBCPP_TYPE_VIS thread; - friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; -}; - template<> struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> : public unary_function<__thread_id, size_t> { _LIBCPP_INLINE_VISIBILITY size_t operator()(__thread_id __v) const _NOEXCEPT { return hash<__libcpp_thread_id>()(__v.__id_); } }; -namespace this_thread -{ - -inline _LIBCPP_INLINE_VISIBILITY -__thread_id -get_id() _NOEXCEPT -{ - return __libcpp_thread_get_current_id(); -} - -} // this_thread +template +_LIBCPP_INLINE_VISIBILITY +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) +{return __os << __id.__id_;} class _LIBCPP_TYPE_VIS thread { __libcpp_thread_t __t_; thread(const thread&); thread& operator=(const thread&); public: typedef __thread_id id; typedef __libcpp_thread_t native_handle_type; _LIBCPP_INLINE_VISIBILITY thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} #ifndef _LIBCPP_CXX03_LANG template ::type, thread>::value >::type > _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp&& __f, _Args&&... __args); #else // _LIBCPP_CXX03_LANG template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f); #endif ~thread(); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;} _LIBCPP_INLINE_VISIBILITY thread& operator=(thread&& __t) _NOEXCEPT; #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} _LIBCPP_INLINE_VISIBILITY bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} void join(); void detach(); _LIBCPP_INLINE_VISIBILITY id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() _NOEXCEPT {return __t_;} static unsigned hardware_concurrency() _NOEXCEPT; }; #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) { __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); } template void* __thread_proxy(void* __vp) { // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...> std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release()); typedef typename __make_tuple_indices::value, 2>::type _Index; __thread_execute(*__p, _Index()); return nullptr; } template thread::thread(_Fp&& __f, _Args&&... __args) { typedef unique_ptr<__thread_struct> _TSPtr; _TSPtr __tsp(new __thread_struct); typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; _VSTD::unique_ptr<_Gp> __p( new _Gp(std::move(__tsp), __decay_copy(_VSTD::forward<_Fp>(__f)), __decay_copy(_VSTD::forward<_Args>(__args))...)); int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); if (__ec == 0) __p.release(); else __throw_system_error(__ec, "thread constructor failed"); } inline thread& thread::operator=(thread&& __t) _NOEXCEPT { if (!__libcpp_thread_isnull(&__t_)) terminate(); __t_ = __t.__t_; __t.__t_ = _LIBCPP_NULL_THREAD; return *this; } #else // _LIBCPP_CXX03_LANG template struct __thread_invoke_pair { // This type is used to pass memory for thread local storage and a functor // to a newly created thread because std::pair doesn't work with // std::unique_ptr in C++03. __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} unique_ptr<__thread_struct> __tsp_; _Fp __fn_; }; template void* __thread_proxy_cxx03(void* __vp) { std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); __thread_local_data().set_pointer(__p->__tsp_.release()); (__p->__fn_)(); return nullptr; } template thread::thread(_Fp __f) { typedef __thread_invoke_pair<_Fp> _InvokePair; typedef std::unique_ptr<_InvokePair> _PairPtr; _PairPtr __pp(new _InvokePair(__f)); int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); if (__ec == 0) __pp.release(); else __throw_system_error(__ec, "thread constructor failed"); } #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_INLINE_VISIBILITY void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} namespace this_thread { _LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); template void sleep_for(const chrono::duration<_Rep, _Period>& __d) { using namespace chrono; if (__d > duration<_Rep, _Period>::zero()) { _LIBCPP_CONSTEXPR duration _Max = nanoseconds::max(); nanoseconds __ns; if (__d < _Max) { __ns = duration_cast(__d); if (__ns < __d) ++__ns; } else __ns = nanoseconds::max(); sleep_for(__ns); } } template void sleep_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; mutex __mut; condition_variable __cv; unique_lock __lk(__mut); while (_Clock::now() < __t) __cv.wait_until(__lk, __t); } template inline _LIBCPP_INLINE_VISIBILITY void sleep_until(const chrono::time_point& __t) { using namespace chrono; sleep_for(__t - steady_clock::now()); } inline _LIBCPP_INLINE_VISIBILITY void yield() _NOEXCEPT {__libcpp_thread_yield();} } // this_thread _LIBCPP_END_NAMESPACE_STD #endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_POP_MACROS #endif // _LIBCPP_THREAD Index: stable/12/contrib/libc++/src/mutex.cpp =================================================================== --- stable/12/contrib/libc++/src/mutex.cpp (revision 351766) +++ stable/12/contrib/libc++/src/mutex.cpp (revision 351767) @@ -1,258 +1,258 @@ //===------------------------- mutex.cpp ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "mutex" #include "limits" #include "system_error" #include "include/atomic_support.h" #include "__undef_macros" _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS const defer_lock_t defer_lock = {}; const try_to_lock_t try_to_lock = {}; const adopt_lock_t adopt_lock = {}; mutex::~mutex() { __libcpp_mutex_destroy(&__m_); } void mutex::lock() { int ec = __libcpp_mutex_lock(&__m_); if (ec) __throw_system_error(ec, "mutex lock failed"); } bool mutex::try_lock() _NOEXCEPT { return __libcpp_mutex_trylock(&__m_); } void mutex::unlock() _NOEXCEPT { int ec = __libcpp_mutex_unlock(&__m_); (void)ec; _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed"); } // recursive_mutex recursive_mutex::recursive_mutex() { int ec = __libcpp_recursive_mutex_init(&__m_); if (ec) __throw_system_error(ec, "recursive_mutex constructor failed"); } recursive_mutex::~recursive_mutex() { int e = __libcpp_recursive_mutex_destroy(&__m_); (void)e; _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed"); } void recursive_mutex::lock() { int ec = __libcpp_recursive_mutex_lock(&__m_); if (ec) __throw_system_error(ec, "recursive_mutex lock failed"); } void recursive_mutex::unlock() _NOEXCEPT { int e = __libcpp_recursive_mutex_unlock(&__m_); (void)e; _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed"); } bool recursive_mutex::try_lock() _NOEXCEPT { return __libcpp_recursive_mutex_trylock(&__m_); } // timed_mutex timed_mutex::timed_mutex() : __locked_(false) { } timed_mutex::~timed_mutex() { lock_guard _(__m_); } void timed_mutex::lock() { unique_lock lk(__m_); while (__locked_) __cv_.wait(lk); __locked_ = true; } bool timed_mutex::try_lock() _NOEXCEPT { unique_lock lk(__m_, try_to_lock); if (lk.owns_lock() && !__locked_) { __locked_ = true; return true; } return false; } void timed_mutex::unlock() _NOEXCEPT { lock_guard _(__m_); __locked_ = false; __cv_.notify_one(); } // recursive_timed_mutex recursive_timed_mutex::recursive_timed_mutex() : __count_(0), - __id_(0) + __id_{} { } recursive_timed_mutex::~recursive_timed_mutex() { lock_guard _(__m_); } void recursive_timed_mutex::lock() { - __libcpp_thread_id id = __libcpp_thread_get_current_id(); + __thread_id id = this_thread::get_id(); unique_lock lk(__m_); - if (__libcpp_thread_id_equal(id, __id_)) + if (id ==__id_) { if (__count_ == numeric_limits::max()) __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); ++__count_; return; } while (__count_ != 0) __cv_.wait(lk); __count_ = 1; __id_ = id; } bool recursive_timed_mutex::try_lock() _NOEXCEPT { - __libcpp_thread_id id = __libcpp_thread_get_current_id(); + __thread_id id = this_thread::get_id(); unique_lock lk(__m_, try_to_lock); - if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_))) + if (lk.owns_lock() && (__count_ == 0 || id == __id_)) { if (__count_ == numeric_limits::max()) return false; ++__count_; __id_ = id; return true; } return false; } void recursive_timed_mutex::unlock() _NOEXCEPT { unique_lock lk(__m_); if (--__count_ == 0) { - __id_ = 0; + __id_.__reset(); lk.unlock(); __cv_.notify_one(); } } #endif // !_LIBCPP_HAS_NO_THREADS // If dispatch_once_f ever handles C++ exceptions, and if one can get to it // without illegal macros (unexpected macros not beginning with _UpperCase or // __lowercase), and if it stops spinning waiting threads, then call_once should // call into dispatch_once_f instead of here. Relevant radar this code needs to // keep in sync with: 7741191. #ifndef _LIBCPP_HAS_NO_THREADS _LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; _LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; #endif void __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) { #if defined(_LIBCPP_HAS_NO_THREADS) if (flag == 0) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS flag = 1; func(arg); flag = ~0ul; #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { flag = 0ul; throw; } #endif // _LIBCPP_NO_EXCEPTIONS } #else // !_LIBCPP_HAS_NO_THREADS __libcpp_mutex_lock(&mut); while (flag == 1) __libcpp_condvar_wait(&cv, &mut); if (flag == 0) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS __libcpp_relaxed_store(&flag, 1ul); __libcpp_mutex_unlock(&mut); func(arg); __libcpp_mutex_lock(&mut); __libcpp_atomic_store(&flag, ~0ul, _AO_Release); __libcpp_mutex_unlock(&mut); __libcpp_condvar_broadcast(&cv); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { __libcpp_mutex_lock(&mut); __libcpp_relaxed_store(&flag, 0ul); __libcpp_mutex_unlock(&mut); __libcpp_condvar_broadcast(&cv); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } else __libcpp_mutex_unlock(&mut); #endif // !_LIBCPP_HAS_NO_THREADS } _LIBCPP_END_NAMESPACE_STD Index: stable/12 =================================================================== --- stable/12 (revision 351766) +++ stable/12 (revision 351767) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r351253