Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__cxx03/__thread/thread.h
213799 views
1
// -*- C++ -*-
2
//===----------------------------------------------------------------------===//
3
//
4
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5
// See https://llvm.org/LICENSE.txt for license information.
6
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef _LIBCPP___CXX03___THREAD_THREAD_H
11
#define _LIBCPP___CXX03___THREAD_THREAD_H
12
13
#include <__cxx03/__condition_variable/condition_variable.h>
14
#include <__cxx03/__config>
15
#include <__cxx03/__exception/terminate.h>
16
#include <__cxx03/__functional/hash.h>
17
#include <__cxx03/__functional/unary_function.h>
18
#include <__cxx03/__memory/unique_ptr.h>
19
#include <__cxx03/__mutex/mutex.h>
20
#include <__cxx03/__system_error/system_error.h>
21
#include <__cxx03/__thread/id.h>
22
#include <__cxx03/__thread/support.h>
23
#include <__cxx03/__utility/forward.h>
24
25
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
26
# include <__cxx03/locale>
27
# include <__cxx03/sstream>
28
#endif
29
30
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
31
# pragma GCC system_header
32
#endif
33
34
_LIBCPP_PUSH_MACROS
35
#include <__cxx03/__undef_macros>
36
37
_LIBCPP_BEGIN_NAMESPACE_STD
38
39
template <class _Tp>
40
class __thread_specific_ptr;
41
class _LIBCPP_EXPORTED_FROM_ABI __thread_struct;
42
class _LIBCPP_HIDDEN __thread_struct_imp;
43
class __assoc_sub_state;
44
45
_LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data();
46
47
class _LIBCPP_EXPORTED_FROM_ABI __thread_struct {
48
__thread_struct_imp* __p_;
49
50
__thread_struct(const __thread_struct&);
51
__thread_struct& operator=(const __thread_struct&);
52
53
public:
54
__thread_struct();
55
~__thread_struct();
56
57
void notify_all_at_thread_exit(condition_variable*, mutex*);
58
void __make_ready_at_thread_exit(__assoc_sub_state*);
59
};
60
61
template <class _Tp>
62
class __thread_specific_ptr {
63
__libcpp_tls_key __key_;
64
65
// Only __thread_local_data() may construct a __thread_specific_ptr
66
// and only with _Tp == __thread_struct.
67
static_assert(is_same<_Tp, __thread_struct>::value, "");
68
__thread_specific_ptr();
69
friend _LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data();
70
71
_LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
72
73
public:
74
typedef _Tp* pointer;
75
76
__thread_specific_ptr(const __thread_specific_ptr&) = delete;
77
__thread_specific_ptr& operator=(const __thread_specific_ptr&) = delete;
78
~__thread_specific_ptr();
79
80
_LIBCPP_HIDE_FROM_ABI pointer get() const { return static_cast<_Tp*>(__libcpp_tls_get(__key_)); }
81
_LIBCPP_HIDE_FROM_ABI pointer operator*() const { return *get(); }
82
_LIBCPP_HIDE_FROM_ABI pointer operator->() const { return get(); }
83
void set_pointer(pointer __p);
84
};
85
86
template <class _Tp>
87
void _LIBCPP_TLS_DESTRUCTOR_CC __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) {
88
delete static_cast<pointer>(__p);
89
}
90
91
template <class _Tp>
92
__thread_specific_ptr<_Tp>::__thread_specific_ptr() {
93
int __ec = __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
94
if (__ec)
95
__throw_system_error(__ec, "__thread_specific_ptr construction failed");
96
}
97
98
template <class _Tp>
99
__thread_specific_ptr<_Tp>::~__thread_specific_ptr() {
100
// __thread_specific_ptr is only created with a static storage duration
101
// so this destructor is only invoked during program termination. Invoking
102
// pthread_key_delete(__key_) may prevent other threads from deleting their
103
// thread local data. For this reason we leak the key.
104
}
105
106
template <class _Tp>
107
void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) {
108
_LIBCPP_ASSERT_INTERNAL(get() == nullptr, "Attempting to overwrite thread local data");
109
std::__libcpp_tls_set(__key_, __p);
110
}
111
112
template <>
113
struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> : public __unary_function<__thread_id, size_t> {
114
_LIBCPP_HIDE_FROM_ABI size_t operator()(__thread_id __v) const _NOEXCEPT {
115
return hash<__libcpp_thread_id>()(__v.__id_);
116
}
117
};
118
119
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
120
template <class _CharT, class _Traits>
121
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
122
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {
123
// [thread.thread.id]/9
124
// Effects: Inserts the text representation for charT of id into out.
125
//
126
// [thread.thread.id]/2
127
// The text representation for the character type charT of an
128
// object of type thread::id is an unspecified sequence of charT
129
// such that, for two objects of type thread::id x and y, if
130
// x == y is true, the thread::id objects have the same text
131
// representation, and if x != y is true, the thread::id objects
132
// have distinct text representations.
133
//
134
// Since various flags in the output stream can affect how the
135
// thread id is represented (e.g. numpunct or showbase), we
136
// use a temporary stream instead and just output the thread
137
// id representation as a string.
138
139
basic_ostringstream<_CharT, _Traits> __sstr;
140
__sstr.imbue(locale::classic());
141
__sstr << __id.__id_;
142
return __os << __sstr.str();
143
}
144
#endif // _LIBCPP_HAS_NO_LOCALIZATION
145
146
class _LIBCPP_EXPORTED_FROM_ABI thread {
147
__libcpp_thread_t __t_;
148
149
thread(const thread&);
150
thread& operator=(const thread&);
151
152
public:
153
typedef __thread_id id;
154
typedef __libcpp_thread_t native_handle_type;
155
156
_LIBCPP_HIDE_FROM_ABI thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}
157
template <class _Fp>
158
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f);
159
~thread();
160
161
_LIBCPP_HIDE_FROM_ABI thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { __t.__t_ = _LIBCPP_NULL_THREAD; }
162
163
_LIBCPP_HIDE_FROM_ABI thread& operator=(thread&& __t) _NOEXCEPT {
164
if (!__libcpp_thread_isnull(&__t_))
165
terminate();
166
__t_ = __t.__t_;
167
__t.__t_ = _LIBCPP_NULL_THREAD;
168
return *this;
169
}
170
171
_LIBCPP_HIDE_FROM_ABI void swap(thread& __t) _NOEXCEPT { std::swap(__t_, __t.__t_); }
172
173
_LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); }
174
void join();
175
void detach();
176
_LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); }
177
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }
178
179
static unsigned hardware_concurrency() _NOEXCEPT;
180
};
181
182
template <class _Fp>
183
struct __thread_invoke_pair {
184
// This type is used to pass memory for thread local storage and a functor
185
// to a newly created thread because std::pair doesn't work with
186
// std::unique_ptr in C++03.
187
_LIBCPP_HIDE_FROM_ABI __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
188
unique_ptr<__thread_struct> __tsp_;
189
_Fp __fn_;
190
};
191
192
template <class _Fp>
193
_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) {
194
unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
195
__thread_local_data().set_pointer(__p->__tsp_.release());
196
(__p->__fn_)();
197
return nullptr;
198
}
199
200
template <class _Fp>
201
thread::thread(_Fp __f) {
202
typedef __thread_invoke_pair<_Fp> _InvokePair;
203
typedef unique_ptr<_InvokePair> _PairPtr;
204
_PairPtr __pp(new _InvokePair(__f));
205
int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
206
if (__ec == 0)
207
__pp.release();
208
else
209
__throw_system_error(__ec, "thread constructor failed");
210
}
211
212
inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); }
213
214
_LIBCPP_END_NAMESPACE_STD
215
216
_LIBCPP_POP_MACROS
217
218
#endif // _LIBCPP___CXX03___THREAD_THREAD_H
219
220