Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/c++/src/thread.cpp
12346 views
1
//===------------------------- thread.cpp----------------------------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "__config"
11
#ifndef _LIBCPP_HAS_NO_THREADS
12
13
#include "thread"
14
#include "exception"
15
#include "vector"
16
#include "future"
17
#include "limits"
18
#include <sys/types.h>
19
20
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
21
# include <sys/param.h>
22
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
23
# include <sys/sysctl.h>
24
# endif
25
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
26
27
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__)
28
# include <unistd.h>
29
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__)
30
31
#if defined(__NetBSD__)
32
#pragma weak pthread_create // Do not create libpthread dependency
33
#endif
34
35
#if defined(_LIBCPP_WIN32API)
36
#include <windows.h>
37
#endif
38
39
_LIBCPP_BEGIN_NAMESPACE_STD
40
41
thread::~thread()
42
{
43
if (!__libcpp_thread_isnull(&__t_))
44
terminate();
45
}
46
47
void
48
thread::join()
49
{
50
int ec = EINVAL;
51
if (!__libcpp_thread_isnull(&__t_))
52
{
53
ec = __libcpp_thread_join(&__t_);
54
if (ec == 0)
55
__t_ = _LIBCPP_NULL_THREAD;
56
}
57
58
if (ec)
59
__throw_system_error(ec, "thread::join failed");
60
}
61
62
void
63
thread::detach()
64
{
65
int ec = EINVAL;
66
if (!__libcpp_thread_isnull(&__t_))
67
{
68
ec = __libcpp_thread_detach(&__t_);
69
if (ec == 0)
70
__t_ = _LIBCPP_NULL_THREAD;
71
}
72
73
if (ec)
74
__throw_system_error(ec, "thread::detach failed");
75
}
76
77
unsigned
78
thread::hardware_concurrency() _NOEXCEPT
79
{
80
#if defined(CTL_HW) && defined(HW_NCPU)
81
unsigned n;
82
int mib[2] = {CTL_HW, HW_NCPU};
83
std::size_t s = sizeof(n);
84
sysctl(mib, 2, &n, &s, 0, 0);
85
return n;
86
#elif defined(_SC_NPROCESSORS_ONLN)
87
long result = sysconf(_SC_NPROCESSORS_ONLN);
88
// sysconf returns -1 if the name is invalid, the option does not exist or
89
// does not have a definite limit.
90
// if sysconf returns some other negative number, we have no idea
91
// what is going on. Default to something safe.
92
if (result < 0)
93
return 0;
94
return static_cast<unsigned>(result);
95
#elif defined(_LIBCPP_WIN32API)
96
SYSTEM_INFO info;
97
GetSystemInfo(&info);
98
return info.dwNumberOfProcessors;
99
#else // defined(CTL_HW) && defined(HW_NCPU)
100
// TODO: grovel through /proc or check cpuid on x86 and similar
101
// instructions on other architectures.
102
# if defined(_LIBCPP_WARNING)
103
_LIBCPP_WARNING("hardware_concurrency not yet implemented")
104
# else
105
# warning hardware_concurrency not yet implemented
106
# endif
107
return 0; // Means not computable [thread.thread.static]
108
#endif // defined(CTL_HW) && defined(HW_NCPU)
109
}
110
111
namespace this_thread
112
{
113
114
void
115
sleep_for(const chrono::nanoseconds& ns)
116
{
117
if (ns > chrono::nanoseconds::zero())
118
{
119
__libcpp_thread_sleep_for(ns);
120
}
121
}
122
123
} // this_thread
124
125
__thread_specific_ptr<__thread_struct>&
126
__thread_local_data()
127
{
128
static __thread_specific_ptr<__thread_struct> __p;
129
return __p;
130
}
131
132
// __thread_struct_imp
133
134
template <class T>
135
class _LIBCPP_HIDDEN __hidden_allocator
136
{
137
public:
138
typedef T value_type;
139
140
T* allocate(size_t __n)
141
{return static_cast<T*>(::operator new(__n * sizeof(T)));}
142
void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));}
143
144
size_t max_size() const {return size_t(~0) / sizeof(T);}
145
};
146
147
class _LIBCPP_HIDDEN __thread_struct_imp
148
{
149
typedef vector<__assoc_sub_state*,
150
__hidden_allocator<__assoc_sub_state*> > _AsyncStates;
151
typedef vector<pair<condition_variable*, mutex*>,
152
__hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
153
154
_AsyncStates async_states_;
155
_Notify notify_;
156
157
__thread_struct_imp(const __thread_struct_imp&);
158
__thread_struct_imp& operator=(const __thread_struct_imp&);
159
public:
160
__thread_struct_imp() {}
161
~__thread_struct_imp();
162
163
void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
164
void __make_ready_at_thread_exit(__assoc_sub_state* __s);
165
};
166
167
__thread_struct_imp::~__thread_struct_imp()
168
{
169
for (_Notify::iterator i = notify_.begin(), e = notify_.end();
170
i != e; ++i)
171
{
172
i->second->unlock();
173
i->first->notify_all();
174
}
175
for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
176
i != e; ++i)
177
{
178
(*i)->__make_ready();
179
(*i)->__release_shared();
180
}
181
}
182
183
void
184
__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
185
{
186
notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
187
}
188
189
void
190
__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
191
{
192
async_states_.push_back(__s);
193
__s->__add_shared();
194
}
195
196
// __thread_struct
197
198
__thread_struct::__thread_struct()
199
: __p_(new __thread_struct_imp)
200
{
201
}
202
203
__thread_struct::~__thread_struct()
204
{
205
delete __p_;
206
}
207
208
void
209
__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
210
{
211
__p_->notify_all_at_thread_exit(cv, m);
212
}
213
214
void
215
__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
216
{
217
__p_->__make_ready_at_thread_exit(__s);
218
}
219
220
_LIBCPP_END_NAMESPACE_STD
221
222
#endif // !_LIBCPP_HAS_NO_THREADS
223
224