blob: 3c1cf99fc9c300134d73b47b5a1fba8b2b1a60f0 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===--------------------------- thread -----------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_THREAD
12#define _LIBCPP_THREAD
13
14/*
15
16 thread synopsis
17
18#define __STDCPP_THREADS __cplusplus
19
20namespace std
21{
22
23class thread
24{
25public:
26 class id;
27 typedef pthread_t native_handle_type;
28
29 thread();
30 template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
31 ~thread();
32
33 thread(const thread&) = delete;
34 thread(thread&& t);
35
36 thread& operator=(const thread&) = delete;
37 thread& operator=(thread&& t);
38
39 void swap(thread& t);
40
41 bool joinable() const;
42 void join();
43 void detach();
44 id get_id() const;
45 native_handle_type native_handle();
46
47 static unsigned hardware_concurrency();
48};
49
50void swap(thread& x, thread& y);
51
52class thread::id
53{
54public:
55 id();
56};
57
58bool operator==(thread::id x, thread::id y);
59bool operator!=(thread::id x, thread::id y);
60bool operator< (thread::id x, thread::id y);
61bool operator<=(thread::id x, thread::id y);
62bool operator> (thread::id x, thread::id y);
63bool operator>=(thread::id x, thread::id y);
64
65template<class charT, class traits>
66basic_ostream<charT, traits>&
67operator<<(basic_ostream<charT, traits>& out, thread::id id);
68
69namespace this_thread
70{
71
72thread::id get_id();
73
74void yield();
75
76template <class Clock, class Duration>
77void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
78
79template <class Rep, class Period>
80void sleep_for(const chrono::duration<Rep, Period>& rel_time);
81
82} // this_thread
83
84} // std
85
86*/
87
88#include <__config>
89#include <iosfwd>
90#include <__functional_base>
91#include <type_traits>
92#include <cstddef>
93#include <functional>
94#include <memory>
95#include <system_error>
96#include <chrono>
97#include <__mutex_base>
98#include <pthread.h>
99
100#pragma GCC system_header
101
102#define __STDCPP_THREADS __cplusplus
103
104_LIBCPP_BEGIN_NAMESPACE_STD
105
106class thread;
107class __thread_id;
108
109namespace this_thread
110{
111
112__thread_id get_id();
113
114} // this_thread
115
116class __thread_id
117{
118 pthread_t __id_;
119
120public:
121 __thread_id() : __id_(0) {}
122
123 friend bool operator==(__thread_id __x, __thread_id __y)
124 {return __x.__id_ == __y.__id_;}
125 friend bool operator!=(__thread_id __x, __thread_id __y)
126 {return !(__x == __y);}
127 friend bool operator< (__thread_id __x, __thread_id __y)
128 {return __x.__id_ < __y.__id_;}
129 friend bool operator<=(__thread_id __x, __thread_id __y)
130 {return !(__y < __x);}
131 friend bool operator> (__thread_id __x, __thread_id __y)
132 {return __y < __x ;}
133 friend bool operator>=(__thread_id __x, __thread_id __y)
134 {return !(__x < __y);}
135
136 template<class _CharT, class _Traits>
137 friend
138 basic_ostream<_CharT, _Traits>&
139 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
140 {return __os << __id.__id_;}
141
142private:
143 __thread_id(pthread_t __id) : __id_(__id) {}
144
145 friend __thread_id this_thread::get_id();
146 friend class thread;
147};
148
149template<class _Tp> struct hash;
150
151template<>
152struct hash<__thread_id>
153 : public unary_function<__thread_id, size_t>
154{
155 size_t operator()(__thread_id __v) const
156 {
157 const size_t* const __p = reinterpret_cast<const size_t*>(&__v);
158 return *__p;
159 }
160};
161
162namespace this_thread
163{
164
165inline
166__thread_id
167get_id()
168{
169 return pthread_self();
170}
171
172} // this_thread
173
174class thread
175{
176 pthread_t __t_;
177
178#ifndef _LIBCPP_MOVE
179 thread(const thread&); // = delete;
180 thread& operator=(const thread&); // = delete;
181#endif
182public:
183 typedef __thread_id id;
184 typedef pthread_t native_handle_type;
185
186 thread() : __t_(0) {}
187#ifndef _LIBCPP_HAS_NO_VARIADICS
188 template <class _F, class ..._Args,
189 class = typename enable_if
190 <
191 !is_same<typename decay<_F>::type, thread>::value
192 >::type
193 >
194 explicit thread(_F&& __f, _Args&&... __args);
195#else
196 template <class _F> explicit thread(_F __f);
197#endif
198 ~thread();
199
200#ifdef _LIBCPP_MOVE
201 thread(const thread&) = delete;
202 thread(thread&& __t) : __t_(__t.__t_) {__t.__t_ = 0;}
203 thread& operator=(const thread&) = delete;
204 thread& operator=(thread&& __t);
205#endif
206
207 void swap(thread& __t) {_STD::swap(__t_, __t.__t_);}
208
209 bool joinable() const {return __t_ != nullptr;}
210 void join();
211 void detach();
212 id get_id() const {return __t_;}
213 native_handle_type native_handle() {return __t_;}
214
215 static unsigned hardware_concurrency();
216};
217
218template <class _F>
219void*
220__thread_proxy(void* __vp)
221{
222 std::unique_ptr<_F> __p(static_cast<_F*>(__vp));
223 (*__p)();
224 return nullptr;
225}
226
227#ifndef _LIBCPP_HAS_NO_VARIADICS
228
229template <class _F, class ..._Args,
230 class
231 >
232thread::thread(_F&& __f, _Args&&... __args)
233{
234 typedef decltype(bind(std::forward<_F>(__f), std::forward<_Args>(__args)...)) _G;
235 std::unique_ptr<_G> __p(new _G(bind(std::forward<_F>(__f),
236 std::forward<_Args>(__args)...)));
237 int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get());
238 if (__ec == 0)
239 __p.release();
240 else
241 __throw_system_error(__ec, "thread constructor failed");
242}
243
244#else
245
246template <class _F>
247thread::thread(_F __f)
248{
249 std::unique_ptr<_F> __p(new _F(__f));
250 int __ec = pthread_create(&__t_, 0, &__thread_proxy<_F>, __p.get());
251 if (__ec == 0)
252 __p.release();
253 else
254 __throw_system_error(__ec, "thread constructor failed");
255}
256
257#endif
258
259#ifdef _LIBCPP_MOVE
260
261inline
262thread&
263thread::operator=(thread&& __t)
264{
265 if (__t_ != nullptr)
266 terminate();
267 __t_ = __t.__t_;
268 __t.__t_ = nullptr;
269 return *this;
270}
271
272#endif
273
274inline
275void swap(thread& __x, thread& __y) {__x.swap(__y);}
276
277
278namespace this_thread
279{
280
281void sleep_for(const chrono::nanoseconds& ns);
282
283template <class _Rep, class _Period>
284void
285sleep_for(const chrono::duration<_Rep, _Period>& __d)
286{
287 using namespace chrono;
288 nanoseconds __ns = duration_cast<nanoseconds>(__d);
289 if (__ns < __d)
290 ++__ns;
291 sleep_for(__ns);
292}
293
294template <class _Clock, class _Duration>
295void
296sleep_until(const chrono::time_point<_Clock, _Duration>& __t)
297{
298 using namespace chrono;
299 mutex __mut;
300 condition_variable __cv;
301 unique_lock<mutex> __lk(__mut);
302 while (_Clock::now() < __t)
303 __cv.wait_until(__lk, __t);
304}
305
306template <class _Duration>
307inline
308void
309sleep_until(const chrono::time_point<chrono::monotonic_clock, _Duration>& __t)
310{
311 using namespace chrono;
312 sleep_for(__t - monotonic_clock::now());
313}
314
315inline
316void yield() {sched_yield();}
317
318} // this_thread
319
320_LIBCPP_END_NAMESPACE_STD
321
322#endif // _LIBCPP_THREAD