Path: blob/main/contrib/llvm-project/libcxx/include/__cxx03/__thread/thread.h
213799 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___CXX03___THREAD_THREAD_H10#define _LIBCPP___CXX03___THREAD_THREAD_H1112#include <__cxx03/__condition_variable/condition_variable.h>13#include <__cxx03/__config>14#include <__cxx03/__exception/terminate.h>15#include <__cxx03/__functional/hash.h>16#include <__cxx03/__functional/unary_function.h>17#include <__cxx03/__memory/unique_ptr.h>18#include <__cxx03/__mutex/mutex.h>19#include <__cxx03/__system_error/system_error.h>20#include <__cxx03/__thread/id.h>21#include <__cxx03/__thread/support.h>22#include <__cxx03/__utility/forward.h>2324#ifndef _LIBCPP_HAS_NO_LOCALIZATION25# include <__cxx03/locale>26# include <__cxx03/sstream>27#endif2829#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)30# pragma GCC system_header31#endif3233_LIBCPP_PUSH_MACROS34#include <__cxx03/__undef_macros>3536_LIBCPP_BEGIN_NAMESPACE_STD3738template <class _Tp>39class __thread_specific_ptr;40class _LIBCPP_EXPORTED_FROM_ABI __thread_struct;41class _LIBCPP_HIDDEN __thread_struct_imp;42class __assoc_sub_state;4344_LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data();4546class _LIBCPP_EXPORTED_FROM_ABI __thread_struct {47__thread_struct_imp* __p_;4849__thread_struct(const __thread_struct&);50__thread_struct& operator=(const __thread_struct&);5152public:53__thread_struct();54~__thread_struct();5556void notify_all_at_thread_exit(condition_variable*, mutex*);57void __make_ready_at_thread_exit(__assoc_sub_state*);58};5960template <class _Tp>61class __thread_specific_ptr {62__libcpp_tls_key __key_;6364// Only __thread_local_data() may construct a __thread_specific_ptr65// and only with _Tp == __thread_struct.66static_assert(is_same<_Tp, __thread_struct>::value, "");67__thread_specific_ptr();68friend _LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data();6970_LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);7172public:73typedef _Tp* pointer;7475__thread_specific_ptr(const __thread_specific_ptr&) = delete;76__thread_specific_ptr& operator=(const __thread_specific_ptr&) = delete;77~__thread_specific_ptr();7879_LIBCPP_HIDE_FROM_ABI pointer get() const { return static_cast<_Tp*>(__libcpp_tls_get(__key_)); }80_LIBCPP_HIDE_FROM_ABI pointer operator*() const { return *get(); }81_LIBCPP_HIDE_FROM_ABI pointer operator->() const { return get(); }82void set_pointer(pointer __p);83};8485template <class _Tp>86void _LIBCPP_TLS_DESTRUCTOR_CC __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) {87delete static_cast<pointer>(__p);88}8990template <class _Tp>91__thread_specific_ptr<_Tp>::__thread_specific_ptr() {92int __ec = __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);93if (__ec)94__throw_system_error(__ec, "__thread_specific_ptr construction failed");95}9697template <class _Tp>98__thread_specific_ptr<_Tp>::~__thread_specific_ptr() {99// __thread_specific_ptr is only created with a static storage duration100// so this destructor is only invoked during program termination. Invoking101// pthread_key_delete(__key_) may prevent other threads from deleting their102// thread local data. For this reason we leak the key.103}104105template <class _Tp>106void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) {107_LIBCPP_ASSERT_INTERNAL(get() == nullptr, "Attempting to overwrite thread local data");108std::__libcpp_tls_set(__key_, __p);109}110111template <>112struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> : public __unary_function<__thread_id, size_t> {113_LIBCPP_HIDE_FROM_ABI size_t operator()(__thread_id __v) const _NOEXCEPT {114return hash<__libcpp_thread_id>()(__v.__id_);115}116};117118#ifndef _LIBCPP_HAS_NO_LOCALIZATION119template <class _CharT, class _Traits>120_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&121operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {122// [thread.thread.id]/9123// Effects: Inserts the text representation for charT of id into out.124//125// [thread.thread.id]/2126// The text representation for the character type charT of an127// object of type thread::id is an unspecified sequence of charT128// such that, for two objects of type thread::id x and y, if129// x == y is true, the thread::id objects have the same text130// representation, and if x != y is true, the thread::id objects131// have distinct text representations.132//133// Since various flags in the output stream can affect how the134// thread id is represented (e.g. numpunct or showbase), we135// use a temporary stream instead and just output the thread136// id representation as a string.137138basic_ostringstream<_CharT, _Traits> __sstr;139__sstr.imbue(locale::classic());140__sstr << __id.__id_;141return __os << __sstr.str();142}143#endif // _LIBCPP_HAS_NO_LOCALIZATION144145class _LIBCPP_EXPORTED_FROM_ABI thread {146__libcpp_thread_t __t_;147148thread(const thread&);149thread& operator=(const thread&);150151public:152typedef __thread_id id;153typedef __libcpp_thread_t native_handle_type;154155_LIBCPP_HIDE_FROM_ABI thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}156template <class _Fp>157_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f);158~thread();159160_LIBCPP_HIDE_FROM_ABI thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { __t.__t_ = _LIBCPP_NULL_THREAD; }161162_LIBCPP_HIDE_FROM_ABI thread& operator=(thread&& __t) _NOEXCEPT {163if (!__libcpp_thread_isnull(&__t_))164terminate();165__t_ = __t.__t_;166__t.__t_ = _LIBCPP_NULL_THREAD;167return *this;168}169170_LIBCPP_HIDE_FROM_ABI void swap(thread& __t) _NOEXCEPT { std::swap(__t_, __t.__t_); }171172_LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); }173void join();174void detach();175_LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); }176_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }177178static unsigned hardware_concurrency() _NOEXCEPT;179};180181template <class _Fp>182struct __thread_invoke_pair {183// This type is used to pass memory for thread local storage and a functor184// to a newly created thread because std::pair doesn't work with185// std::unique_ptr in C++03.186_LIBCPP_HIDE_FROM_ABI __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}187unique_ptr<__thread_struct> __tsp_;188_Fp __fn_;189};190191template <class _Fp>192_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) {193unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));194__thread_local_data().set_pointer(__p->__tsp_.release());195(__p->__fn_)();196return nullptr;197}198199template <class _Fp>200thread::thread(_Fp __f) {201typedef __thread_invoke_pair<_Fp> _InvokePair;202typedef unique_ptr<_InvokePair> _PairPtr;203_PairPtr __pp(new _InvokePair(__f));204int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());205if (__ec == 0)206__pp.release();207else208__throw_system_error(__ec, "thread constructor failed");209}210211inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); }212213_LIBCPP_END_NAMESPACE_STD214215_LIBCPP_POP_MACROS216217#endif // _LIBCPP___CXX03___THREAD_THREAD_H218219220