thread revision 249989
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
29241900Sdim    thread() noexcept;
30227825Stheraven    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
31227825Stheraven    ~thread();
32227825Stheraven
33227825Stheraven    thread(const thread&) = delete;
34241900Sdim    thread(thread&& t) noexcept;
35227825Stheraven
36227825Stheraven    thread& operator=(const thread&) = delete;
37241900Sdim    thread& operator=(thread&& t) noexcept;
38227825Stheraven
39241900Sdim    void swap(thread& t) noexcept;
40227825Stheraven
41241900Sdim    bool joinable() const noexcept;
42227825Stheraven    void join();
43227825Stheraven    void detach();
44241900Sdim    id get_id() const noexcept;
45227825Stheraven    native_handle_type native_handle();
46227825Stheraven
47241900Sdim    static unsigned hardware_concurrency() noexcept;
48227825Stheraven};
49227825Stheraven
50241900Sdimvoid swap(thread& x, thread& y) noexcept;
51227825Stheraven
52227825Stheravenclass thread::id
53227825Stheraven{
54227825Stheravenpublic:
55241900Sdim    id() noexcept;
56227825Stheraven};
57227825Stheraven
58241900Sdimbool operator==(thread::id x, thread::id y) noexcept;
59241900Sdimbool operator!=(thread::id x, thread::id y) noexcept;
60241900Sdimbool operator< (thread::id x, thread::id y) noexcept;
61241900Sdimbool operator<=(thread::id x, thread::id y) noexcept;
62241900Sdimbool operator> (thread::id x, thread::id y) noexcept;
63241900Sdimbool operator>=(thread::id x, thread::id y) noexcept;
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
72241900Sdimthread::id get_id() noexcept;
73227825Stheraven
74241900Sdimvoid yield() noexcept;
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);
147249989Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
148227825Stheraven    if (__ec)
149227825Stheraven        throw system_error(error_code(__ec, system_category()),
150227825Stheraven                           "__thread_specific_ptr construction failed");
151249989Sdim#endif
152227825Stheraven}
153227825Stheraven
154227825Stheraventemplate <class _Tp>
155227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
156227825Stheraven{
157227825Stheraven    pthread_key_delete(__key_);
158227825Stheraven}
159227825Stheraven
160227825Stheraventemplate <class _Tp>
161227825Stheraventypename __thread_specific_ptr<_Tp>::pointer
162227825Stheraven__thread_specific_ptr<_Tp>::release()
163227825Stheraven{
164227825Stheraven    pointer __p = get();
165227825Stheraven    pthread_setspecific(__key_, 0);
166227825Stheraven    return __p;
167227825Stheraven}
168227825Stheraven
169227825Stheraventemplate <class _Tp>
170227825Stheravenvoid
171227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p)
172227825Stheraven{
173227825Stheraven    pointer __p_old = get();
174227825Stheraven    pthread_setspecific(__key_, __p);
175227825Stheraven    delete __p_old;
176227825Stheraven}
177227825Stheraven
178249989Sdimclass _LIBCPP_TYPE_VIS thread;
179249989Sdimclass _LIBCPP_TYPE_VIS __thread_id;
180227825Stheraven
181227825Stheravennamespace this_thread
182227825Stheraven{
183227825Stheraven
184241900Sdim_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
185227825Stheraven
186227825Stheraven}  // this_thread
187227825Stheraven
188249989Sdimclass _LIBCPP_TYPE_VIS __thread_id;
189249989Sdimtemplate<> struct _LIBCPP_TYPE_VIS hash<__thread_id>;
190232924Stheraven
191249989Sdimclass _LIBCPP_TYPE_VIS __thread_id
192227825Stheraven{
193227825Stheraven    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
194227825Stheraven    // NULL is the no-thread value on Darwin.  Someone needs to check
195227825Stheraven    // on other platforms.  We assume 0 works everywhere for now.
196227825Stheraven    pthread_t __id_;
197227825Stheraven
198227825Stheravenpublic:
199227825Stheraven    _LIBCPP_INLINE_VISIBILITY
200241900Sdim    __thread_id() _NOEXCEPT : __id_(0) {}
201227825Stheraven
202227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
203241900Sdim        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
204227825Stheraven        {return __x.__id_ == __y.__id_;}
205227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
206241900Sdim        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
207227825Stheraven        {return !(__x == __y);}
208227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
209241900Sdim        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
210227825Stheraven        {return __x.__id_ < __y.__id_;}
211227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
212241900Sdim        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
213227825Stheraven        {return !(__y < __x);}
214227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
215241900Sdim        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
216227825Stheraven        {return   __y < __x ;}
217227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
218241900Sdim        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
219227825Stheraven        {return !(__x < __y);}
220227825Stheraven
221227825Stheraven    template<class _CharT, class _Traits>
222227825Stheraven    friend
223227825Stheraven    _LIBCPP_INLINE_VISIBILITY
224227825Stheraven    basic_ostream<_CharT, _Traits>&
225227825Stheraven    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
226227825Stheraven        {return __os << __id.__id_;}
227227825Stheraven
228227825Stheravenprivate:
229227825Stheraven    _LIBCPP_INLINE_VISIBILITY
230227825Stheraven    __thread_id(pthread_t __id) : __id_(__id) {}
231227825Stheraven
232241900Sdim    friend __thread_id this_thread::get_id() _NOEXCEPT;
233249989Sdim    friend class _LIBCPP_TYPE_VIS thread;
234249989Sdim    friend struct _LIBCPP_TYPE_VIS hash<__thread_id>;
235227825Stheraven};
236227825Stheraven
237227825Stheraventemplate<>
238249989Sdimstruct _LIBCPP_TYPE_VIS hash<__thread_id>
239227825Stheraven    : public unary_function<__thread_id, size_t>
240227825Stheraven{
241227825Stheraven    _LIBCPP_INLINE_VISIBILITY
242227825Stheraven    size_t operator()(__thread_id __v) const
243227825Stheraven    {
244232924Stheraven        return hash<pthread_t>()(__v.__id_);
245227825Stheraven    }
246227825Stheraven};
247227825Stheraven
248227825Stheravennamespace this_thread
249227825Stheraven{
250227825Stheraven
251227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
252227825Stheraven__thread_id
253241900Sdimget_id() _NOEXCEPT
254227825Stheraven{
255227825Stheraven    return pthread_self();
256227825Stheraven}
257227825Stheraven
258227825Stheraven}  // this_thread
259227825Stheraven
260249989Sdimclass _LIBCPP_TYPE_VIS thread
261227825Stheraven{
262227825Stheraven    pthread_t __t_;
263227825Stheraven
264227825Stheraven    thread(const thread&);
265227825Stheraven    thread& operator=(const thread&);
266227825Stheravenpublic:
267227825Stheraven    typedef __thread_id id;
268227825Stheraven    typedef pthread_t native_handle_type;
269227825Stheraven
270227825Stheraven    _LIBCPP_INLINE_VISIBILITY
271241900Sdim    thread() _NOEXCEPT : __t_(0) {}
272227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
273232924Stheraven    template <class _Fp, class ..._Args,
274227825Stheraven              class = typename enable_if
275227825Stheraven              <
276232924Stheraven                   !is_same<typename decay<_Fp>::type, thread>::value
277227825Stheraven              >::type
278227825Stheraven             >
279232924Stheraven        explicit thread(_Fp&& __f, _Args&&... __args);
280227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
281232924Stheraven    template <class _Fp> explicit thread(_Fp __f);
282227825Stheraven#endif
283227825Stheraven    ~thread();
284227825Stheraven
285227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
286227825Stheraven    _LIBCPP_INLINE_VISIBILITY
287241900Sdim    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;}
288241900Sdim    thread& operator=(thread&& __t) _NOEXCEPT;
289227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
290227825Stheraven
291227825Stheraven    _LIBCPP_INLINE_VISIBILITY
292241900Sdim    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
293227825Stheraven
294227825Stheraven    _LIBCPP_INLINE_VISIBILITY
295241900Sdim    bool joinable() const _NOEXCEPT {return __t_ != 0;}
296227825Stheraven    void join();
297227825Stheraven    void detach();
298227825Stheraven    _LIBCPP_INLINE_VISIBILITY
299241900Sdim    id get_id() const _NOEXCEPT {return __t_;}
300227825Stheraven    _LIBCPP_INLINE_VISIBILITY
301241900Sdim    native_handle_type native_handle() _NOEXCEPT {return __t_;}
302227825Stheraven
303241900Sdim    static unsigned hardware_concurrency() _NOEXCEPT;
304227825Stheraven};
305227825Stheraven
306227825Stheravenclass __assoc_sub_state;
307227825Stheraven
308227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp;
309227825Stheraven
310227825Stheravenclass __thread_struct
311227825Stheraven{
312227825Stheraven    __thread_struct_imp* __p_;
313227825Stheraven
314227825Stheraven    __thread_struct(const __thread_struct&);
315227825Stheraven    __thread_struct& operator=(const __thread_struct&);
316227825Stheravenpublic:
317227825Stheraven    __thread_struct();
318227825Stheraven    ~__thread_struct();
319227825Stheraven
320227825Stheraven    void notify_all_at_thread_exit(condition_variable*, mutex*);
321227825Stheraven    void __make_ready_at_thread_exit(__assoc_sub_state*);
322227825Stheraven};
323227825Stheraven
324227825Stheraven__thread_specific_ptr<__thread_struct>& __thread_local_data();
325227825Stheraven
326227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
327227825Stheraven
328232924Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices>
329227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
330227825Stheravenvoid
331249989Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
332227825Stheraven{
333227825Stheraven    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
334227825Stheraven}
335227825Stheraven
336232924Stheraventemplate <class _Fp>
337227825Stheravenvoid*
338227825Stheraven__thread_proxy(void* __vp)
339227825Stheraven{
340227825Stheraven    __thread_local_data().reset(new __thread_struct);
341232924Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
342232924Stheraven    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
343249989Sdim    __thread_execute(*__p, _Index());
344227825Stheraven    return nullptr;
345227825Stheraven}
346227825Stheraven
347232924Stheraventemplate <class _Fp, class ..._Args,
348227825Stheraven          class
349227825Stheraven         >
350232924Stheraventhread::thread(_Fp&& __f, _Args&&... __args)
351227825Stheraven{
352232924Stheraven    typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
353232924Stheraven    _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)),
354227825Stheraven                                __decay_copy(_VSTD::forward<_Args>(__args))...));
355232924Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
356227825Stheraven    if (__ec == 0)
357227825Stheraven        __p.release();
358227825Stheraven    else
359227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
360227825Stheraven}
361227825Stheraven
362227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
363227825Stheraven
364232924Stheraventemplate <class _Fp>
365227825Stheravenvoid*
366227825Stheraven__thread_proxy(void* __vp)
367227825Stheraven{
368227825Stheraven    __thread_local_data().reset(new __thread_struct);
369232924Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
370227825Stheraven    (*__p)();
371227825Stheraven    return nullptr;
372227825Stheraven}
373227825Stheraven
374232924Stheraventemplate <class _Fp>
375232924Stheraventhread::thread(_Fp __f)
376227825Stheraven{
377232924Stheraven    std::unique_ptr<_Fp> __p(new _Fp(__f));
378232924Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get());
379227825Stheraven    if (__ec == 0)
380227825Stheraven        __p.release();
381227825Stheraven    else
382227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
383227825Stheraven}
384227825Stheraven
385227825Stheraven#endif  // _LIBCPP_HAS_NO_VARIADICS
386227825Stheraven
387227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
388227825Stheraven
389227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
390227825Stheraventhread&
391241900Sdimthread::operator=(thread&& __t) _NOEXCEPT
392227825Stheraven{
393227825Stheraven    if (__t_ != 0)
394227825Stheraven        terminate();
395227825Stheraven    __t_ = __t.__t_;
396227825Stheraven    __t.__t_ = 0;
397227825Stheraven    return *this;
398227825Stheraven}
399227825Stheraven
400227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
401227825Stheraven
402227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
403241900Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
404227825Stheraven
405227825Stheravennamespace this_thread
406227825Stheraven{
407227825Stheraven
408227825Stheravenvoid sleep_for(const chrono::nanoseconds& ns);
409227825Stheraven
410227825Stheraventemplate <class _Rep, class _Period>
411227825Stheravenvoid
412227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d)
413227825Stheraven{
414227825Stheraven    using namespace chrono;
415241900Sdim    if (__d > duration<_Rep, _Period>::zero())
416241900Sdim    {
417241900Sdim        _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
418241900Sdim        nanoseconds __ns;
419241900Sdim        if (__d < _Max)
420241900Sdim        {
421241900Sdim            __ns = duration_cast<nanoseconds>(__d);
422241900Sdim            if (__ns < __d)
423241900Sdim                ++__ns;
424241900Sdim        }
425241900Sdim        else
426241900Sdim            __ns = nanoseconds::max();
427241900Sdim        sleep_for(__ns);
428241900Sdim    }
429227825Stheraven}
430227825Stheraven
431227825Stheraventemplate <class _Clock, class _Duration>
432227825Stheravenvoid
433227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t)
434227825Stheraven{
435227825Stheraven    using namespace chrono;
436227825Stheraven    mutex __mut;
437227825Stheraven    condition_variable __cv;
438227825Stheraven    unique_lock<mutex> __lk(__mut);
439227825Stheraven    while (_Clock::now() < __t)
440227825Stheraven        __cv.wait_until(__lk, __t);
441227825Stheraven}
442227825Stheraven
443227825Stheraventemplate <class _Duration>
444227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
445227825Stheravenvoid
446227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
447227825Stheraven{
448227825Stheraven    using namespace chrono;
449227825Stheraven    sleep_for(__t - steady_clock::now());
450227825Stheraven}
451227825Stheraven
452227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
453241900Sdimvoid yield() _NOEXCEPT {sched_yield();}
454227825Stheraven
455227825Stheraven}  // this_thread
456227825Stheraven
457227825Stheraven_LIBCPP_END_NAMESPACE_STD
458227825Stheraven
459227825Stheraven#endif  // _LIBCPP_THREAD
460