thread revision 227825
1227825Stheraven// -*- C++ -*-
2227825Stheraven//===--------------------------- thread -----------------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP_THREAD
12227825Stheraven#define _LIBCPP_THREAD
13227825Stheraven
14227825Stheraven/*
15227825Stheraven
16227825Stheraven    thread synopsis
17227825Stheraven
18227825Stheraven#define __STDCPP_THREADS__ __cplusplus
19227825Stheraven
20227825Stheravennamespace std
21227825Stheraven{
22227825Stheraven
23227825Stheravenclass thread
24227825Stheraven{
25227825Stheravenpublic:
26227825Stheraven    class id;
27227825Stheraven    typedef pthread_t native_handle_type;
28227825Stheraven
29227825Stheraven    thread();
30227825Stheraven    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
31227825Stheraven    ~thread();
32227825Stheraven
33227825Stheraven    thread(const thread&) = delete;
34227825Stheraven    thread(thread&& t);
35227825Stheraven
36227825Stheraven    thread& operator=(const thread&) = delete;
37227825Stheraven    thread& operator=(thread&& t);
38227825Stheraven
39227825Stheraven    void swap(thread& t);
40227825Stheraven
41227825Stheraven    bool joinable() const;
42227825Stheraven    void join();
43227825Stheraven    void detach();
44227825Stheraven    id get_id() const;
45227825Stheraven    native_handle_type native_handle();
46227825Stheraven
47227825Stheraven    static unsigned hardware_concurrency();
48227825Stheraven};
49227825Stheraven
50227825Stheravenvoid swap(thread& x, thread& y);
51227825Stheraven
52227825Stheravenclass thread::id
53227825Stheraven{
54227825Stheravenpublic:
55227825Stheraven    id();
56227825Stheraven};
57227825Stheraven
58227825Stheravenbool operator==(thread::id x, thread::id y);
59227825Stheravenbool operator!=(thread::id x, thread::id y);
60227825Stheravenbool operator< (thread::id x, thread::id y);
61227825Stheravenbool operator<=(thread::id x, thread::id y);
62227825Stheravenbool operator> (thread::id x, thread::id y);
63227825Stheravenbool operator>=(thread::id x, thread::id y);
64227825Stheraven
65227825Stheraventemplate<class charT, class traits>
66227825Stheravenbasic_ostream<charT, traits>&
67227825Stheravenoperator<<(basic_ostream<charT, traits>& out, thread::id id);
68227825Stheraven
69227825Stheravennamespace this_thread
70227825Stheraven{
71227825Stheraven
72227825Stheraventhread::id get_id();
73227825Stheraven
74227825Stheravenvoid yield();
75227825Stheraven
76227825Stheraventemplate <class Clock, class Duration>
77227825Stheravenvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
78227825Stheraven
79227825Stheraventemplate <class Rep, class Period>
80227825Stheravenvoid sleep_for(const chrono::duration<Rep, Period>& rel_time);
81227825Stheraven
82227825Stheraven}  // this_thread
83227825Stheraven
84227825Stheraven}  // std
85227825Stheraven
86227825Stheraven*/
87227825Stheraven
88227825Stheraven#include <__config>
89227825Stheraven#include <iosfwd>
90227825Stheraven#include <__functional_base>
91227825Stheraven#include <type_traits>
92227825Stheraven#include <cstddef>
93227825Stheraven#include <functional>
94227825Stheraven#include <memory>
95227825Stheraven#include <system_error>
96227825Stheraven#include <chrono>
97227825Stheraven#include <__mutex_base>
98227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
99227825Stheraven#include <tuple>
100227825Stheraven#endif
101227825Stheraven#include <pthread.h>
102227825Stheraven
103227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
104227825Stheraven#pragma GCC system_header
105227825Stheraven#endif
106227825Stheraven
107227825Stheraven#define __STDCPP_THREADS__ __cplusplus
108227825Stheraven
109227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
110227825Stheraven
111227825Stheraventemplate <class _Tp>
112227825Stheravenclass __thread_specific_ptr
113227825Stheraven{
114227825Stheraven    pthread_key_t __key_;
115227825Stheraven
116227825Stheraven    __thread_specific_ptr(const __thread_specific_ptr&);
117227825Stheraven    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
118227825Stheraven
119227825Stheraven    static void __at_thread_exit(void*);
120227825Stheravenpublic:
121227825Stheraven    typedef _Tp* pointer;
122227825Stheraven
123227825Stheraven    __thread_specific_ptr();
124227825Stheraven    ~__thread_specific_ptr();
125227825Stheraven
126227825Stheraven    _LIBCPP_INLINE_VISIBILITY
127227825Stheraven    pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));}
128227825Stheraven    _LIBCPP_INLINE_VISIBILITY
129227825Stheraven    pointer operator*() const {return *get();}
130227825Stheraven    _LIBCPP_INLINE_VISIBILITY
131227825Stheraven    pointer operator->() const {return get();}
132227825Stheraven    pointer release();
133227825Stheraven    void reset(pointer __p = nullptr);
134227825Stheraven};
135227825Stheraven
136227825Stheraventemplate <class _Tp>
137227825Stheravenvoid
138227825Stheraven__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
139227825Stheraven{
140227825Stheraven    delete static_cast<pointer>(__p);
141227825Stheraven}
142227825Stheraven
143227825Stheraventemplate <class _Tp>
144227825Stheraven__thread_specific_ptr<_Tp>::__thread_specific_ptr()
145227825Stheraven{
146227825Stheraven    int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
147227825Stheraven    if (__ec)
148227825Stheraven        throw system_error(error_code(__ec, system_category()),
149227825Stheraven                           "__thread_specific_ptr construction failed");
150227825Stheraven}
151227825Stheraven
152227825Stheraventemplate <class _Tp>
153227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
154227825Stheraven{
155227825Stheraven    pthread_key_delete(__key_);
156227825Stheraven}
157227825Stheraven
158227825Stheraventemplate <class _Tp>
159227825Stheraventypename __thread_specific_ptr<_Tp>::pointer
160227825Stheraven__thread_specific_ptr<_Tp>::release()
161227825Stheraven{
162227825Stheraven    pointer __p = get();
163227825Stheraven    pthread_setspecific(__key_, 0);
164227825Stheraven    return __p;
165227825Stheraven}
166227825Stheraven
167227825Stheraventemplate <class _Tp>
168227825Stheravenvoid
169227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p)
170227825Stheraven{
171227825Stheraven    pointer __p_old = get();
172227825Stheraven    pthread_setspecific(__key_, __p);
173227825Stheraven    delete __p_old;
174227825Stheraven}
175227825Stheraven
176227825Stheravenclass thread;
177227825Stheravenclass __thread_id;
178227825Stheraven
179227825Stheravennamespace this_thread
180227825Stheraven{
181227825Stheraven
182227825Stheraven__thread_id get_id();
183227825Stheraven
184227825Stheraven}  // this_thread
185227825Stheraven
186227825Stheravenclass _LIBCPP_VISIBLE __thread_id
187227825Stheraven{
188227825Stheraven    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
189227825Stheraven    // NULL is the no-thread value on Darwin.  Someone needs to check
190227825Stheraven    // on other platforms.  We assume 0 works everywhere for now.
191227825Stheraven    pthread_t __id_;
192227825Stheraven
193227825Stheravenpublic:
194227825Stheraven    _LIBCPP_INLINE_VISIBILITY
195227825Stheraven    __thread_id() : __id_(0) {}
196227825Stheraven
197227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
198227825Stheraven        bool operator==(__thread_id __x, __thread_id __y)
199227825Stheraven        {return __x.__id_ == __y.__id_;}
200227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
201227825Stheraven        bool operator!=(__thread_id __x, __thread_id __y)
202227825Stheraven        {return !(__x == __y);}
203227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
204227825Stheraven        bool operator< (__thread_id __x, __thread_id __y)
205227825Stheraven        {return __x.__id_ < __y.__id_;}
206227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
207227825Stheraven        bool operator<=(__thread_id __x, __thread_id __y)
208227825Stheraven        {return !(__y < __x);}
209227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
210227825Stheraven        bool operator> (__thread_id __x, __thread_id __y)
211227825Stheraven        {return   __y < __x ;}
212227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
213227825Stheraven        bool operator>=(__thread_id __x, __thread_id __y)
214227825Stheraven        {return !(__x < __y);}
215227825Stheraven
216227825Stheraven    template<class _CharT, class _Traits>
217227825Stheraven    friend
218227825Stheraven    _LIBCPP_INLINE_VISIBILITY
219227825Stheraven    basic_ostream<_CharT, _Traits>&
220227825Stheraven    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
221227825Stheraven        {return __os << __id.__id_;}
222227825Stheraven
223227825Stheravenprivate:
224227825Stheraven    _LIBCPP_INLINE_VISIBILITY
225227825Stheraven    __thread_id(pthread_t __id) : __id_(__id) {}
226227825Stheraven
227227825Stheraven    friend __thread_id this_thread::get_id();
228227825Stheraven    friend class _LIBCPP_VISIBLE thread;
229227825Stheraven};
230227825Stheraven
231227825Stheraventemplate<class _Tp> struct hash;
232227825Stheraven
233227825Stheraventemplate<>
234227825Stheravenstruct _LIBCPP_VISIBLE hash<__thread_id>
235227825Stheraven    : public unary_function<__thread_id, size_t>
236227825Stheraven{
237227825Stheraven    _LIBCPP_INLINE_VISIBILITY
238227825Stheraven    size_t operator()(__thread_id __v) const
239227825Stheraven    {
240227825Stheraven        const size_t* const __p = reinterpret_cast<const size_t*>(&__v);
241227825Stheraven        return *__p;
242227825Stheraven    }
243227825Stheraven};
244227825Stheraven
245227825Stheravennamespace this_thread
246227825Stheraven{
247227825Stheraven
248227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
249227825Stheraven__thread_id
250227825Stheravenget_id()
251227825Stheraven{
252227825Stheraven    return pthread_self();
253227825Stheraven}
254227825Stheraven
255227825Stheraven}  // this_thread
256227825Stheraven
257227825Stheravenclass _LIBCPP_VISIBLE thread
258227825Stheraven{
259227825Stheraven    pthread_t __t_;
260227825Stheraven
261227825Stheraven    thread(const thread&);
262227825Stheraven    thread& operator=(const thread&);
263227825Stheravenpublic:
264227825Stheraven    typedef __thread_id id;
265227825Stheraven    typedef pthread_t native_handle_type;
266227825Stheraven
267227825Stheraven    _LIBCPP_INLINE_VISIBILITY
268227825Stheraven    thread() : __t_(0) {}
269227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
270227825Stheraven    template <class _F, class ..._Args,
271227825Stheraven              class = typename enable_if
272227825Stheraven              <
273227825Stheraven                   !is_same<typename decay<_F>::type, thread>::value
274227825Stheraven              >::type
275227825Stheraven             >
276227825Stheraven        explicit thread(_F&& __f, _Args&&... __args);
277227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
278227825Stheraven    template <class _F> explicit thread(_F __f);
279227825Stheraven#endif
280227825Stheraven    ~thread();
281227825Stheraven
282227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
283227825Stheraven    _LIBCPP_INLINE_VISIBILITY
284227825Stheraven    thread(thread&& __t) : __t_(__t.__t_) {__t.__t_ = 0;}
285227825Stheraven    thread& operator=(thread&& __t);
286227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
287227825Stheraven
288227825Stheraven    _LIBCPP_INLINE_VISIBILITY
289227825Stheraven    void swap(thread& __t) {_VSTD::swap(__t_, __t.__t_);}
290227825Stheraven
291227825Stheraven    _LIBCPP_INLINE_VISIBILITY
292227825Stheraven    bool joinable() const {return __t_ != 0;}
293227825Stheraven    void join();
294227825Stheraven    void detach();
295227825Stheraven    _LIBCPP_INLINE_VISIBILITY
296227825Stheraven    id get_id() const {return __t_;}
297227825Stheraven    _LIBCPP_INLINE_VISIBILITY
298227825Stheraven    native_handle_type native_handle() {return __t_;}
299227825Stheraven
300227825Stheraven    static unsigned hardware_concurrency();
301227825Stheraven};
302227825Stheraven
303227825Stheravenclass __assoc_sub_state;
304227825Stheraven
305227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp;
306227825Stheraven
307227825Stheravenclass __thread_struct
308227825Stheraven{
309227825Stheraven    __thread_struct_imp* __p_;
310227825Stheraven
311227825Stheraven    __thread_struct(const __thread_struct&);
312227825Stheraven    __thread_struct& operator=(const __thread_struct&);
313227825Stheravenpublic:
314227825Stheraven    __thread_struct();
315227825Stheraven    ~__thread_struct();
316227825Stheraven
317227825Stheraven    void notify_all_at_thread_exit(condition_variable*, mutex*);
318227825Stheraven    void __make_ready_at_thread_exit(__assoc_sub_state*);
319227825Stheraven};
320227825Stheraven
321227825Stheraven__thread_specific_ptr<__thread_struct>& __thread_local_data();
322227825Stheraven
323227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
324227825Stheraven
325227825Stheraventemplate <class _F, class ..._Args, size_t ..._Indices>
326227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
327227825Stheravenvoid
328227825Stheraven__threaad_execute(tuple<_F, _Args...>& __t, __tuple_indices<_Indices...>)
329227825Stheraven{
330227825Stheraven    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
331227825Stheraven}
332227825Stheraven
333227825Stheraventemplate <class _F>
334227825Stheravenvoid*
335227825Stheraven__thread_proxy(void* __vp)
336227825Stheraven{
337227825Stheraven    __thread_local_data().reset(new __thread_struct);
338227825Stheraven    std::unique_ptr<_F> __p(static_cast<_F*>(__vp));
339227825Stheraven    typedef typename __make_tuple_indices<tuple_size<_F>::value, 1>::type _Index;
340227825Stheraven    __threaad_execute(*__p, _Index());
341227825Stheraven    return nullptr;
342227825Stheraven}
343227825Stheraven
344227825Stheraventemplate <class _F, class ..._Args,
345227825Stheraven          class
346227825Stheraven         >
347227825Stheraventhread::thread(_F&& __f, _Args&&... __args)
348227825Stheraven{
349227825Stheraven    typedef tuple<typename decay<_F>::type, typename decay<_Args>::type...> _G;
350227825Stheraven    _VSTD::unique_ptr<_G> __p(new _G(__decay_copy(_VSTD::forward<_F>(__f)),
351227825Stheraven                                __decay_copy(_VSTD::forward<_Args>(__args))...));
352227825Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get());
353227825Stheraven    if (__ec == 0)
354227825Stheraven        __p.release();
355227825Stheraven    else
356227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
357227825Stheraven}
358227825Stheraven
359227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
360227825Stheraven
361227825Stheraventemplate <class _F>
362227825Stheravenvoid*
363227825Stheraven__thread_proxy(void* __vp)
364227825Stheraven{
365227825Stheraven    __thread_local_data().reset(new __thread_struct);
366227825Stheraven    std::unique_ptr<_F> __p(static_cast<_F*>(__vp));
367227825Stheraven    (*__p)();
368227825Stheraven    return nullptr;
369227825Stheraven}
370227825Stheraven
371227825Stheraventemplate <class _F>
372227825Stheraventhread::thread(_F __f)
373227825Stheraven{
374227825Stheraven    std::unique_ptr<_F> __p(new _F(__f));
375227825Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_F>, __p.get());
376227825Stheraven    if (__ec == 0)
377227825Stheraven        __p.release();
378227825Stheraven    else
379227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
380227825Stheraven}
381227825Stheraven
382227825Stheraven#endif  // _LIBCPP_HAS_NO_VARIADICS
383227825Stheraven
384227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
385227825Stheraven
386227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
387227825Stheraventhread&
388227825Stheraventhread::operator=(thread&& __t)
389227825Stheraven{
390227825Stheraven    if (__t_ != 0)
391227825Stheraven        terminate();
392227825Stheraven    __t_ = __t.__t_;
393227825Stheraven    __t.__t_ = 0;
394227825Stheraven    return *this;
395227825Stheraven}
396227825Stheraven
397227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
398227825Stheraven
399227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
400227825Stheravenvoid swap(thread& __x, thread& __y) {__x.swap(__y);}
401227825Stheraven
402227825Stheravennamespace this_thread
403227825Stheraven{
404227825Stheraven
405227825Stheravenvoid sleep_for(const chrono::nanoseconds& ns);
406227825Stheraven
407227825Stheraventemplate <class _Rep, class _Period>
408227825Stheravenvoid
409227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d)
410227825Stheraven{
411227825Stheraven    using namespace chrono;
412227825Stheraven    nanoseconds __ns = duration_cast<nanoseconds>(__d);
413227825Stheraven    if (__ns < __d)
414227825Stheraven        ++__ns;
415227825Stheraven    sleep_for(__ns);
416227825Stheraven}
417227825Stheraven
418227825Stheraventemplate <class _Clock, class _Duration>
419227825Stheravenvoid
420227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t)
421227825Stheraven{
422227825Stheraven    using namespace chrono;
423227825Stheraven    mutex __mut;
424227825Stheraven    condition_variable __cv;
425227825Stheraven    unique_lock<mutex> __lk(__mut);
426227825Stheraven    while (_Clock::now() < __t)
427227825Stheraven        __cv.wait_until(__lk, __t);
428227825Stheraven}
429227825Stheraven
430227825Stheraventemplate <class _Duration>
431227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
432227825Stheravenvoid
433227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
434227825Stheraven{
435227825Stheraven    using namespace chrono;
436227825Stheraven    sleep_for(__t - steady_clock::now());
437227825Stheraven}
438227825Stheraven
439227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
440227825Stheravenvoid yield() {sched_yield();}
441227825Stheraven
442227825Stheraven}  // this_thread
443227825Stheraven
444227825Stheraven_LIBCPP_END_NAMESPACE_STD
445227825Stheraven
446227825Stheraven#endif  // _LIBCPP_THREAD
447