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>
102276792Sdim#include <sched.h>
103227825Stheraven
104227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
105227825Stheraven#pragma GCC system_header
106227825Stheraven#endif
107227825Stheraven
108227825Stheraven#define __STDCPP_THREADS__ __cplusplus
109227825Stheraven
110276792Sdim#ifdef _LIBCPP_HAS_NO_THREADS
111276792Sdim#error <thread> is not supported on this single threaded system
112276792Sdim#else // !_LIBCPP_HAS_NO_THREADS
113276792Sdim
114227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
115227825Stheraven
116300770Sdimtemplate <class _Tp> class __thread_specific_ptr;
117300770Sdimclass _LIBCPP_TYPE_VIS __thread_struct;
118300770Sdimclass _LIBCPP_HIDDEN __thread_struct_imp;
119300770Sdimclass __assoc_sub_state;
120300770Sdim
121300770Sdim_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
122300770Sdim
123300770Sdimclass _LIBCPP_TYPE_VIS __thread_struct
124300770Sdim{
125300770Sdim    __thread_struct_imp* __p_;
126300770Sdim
127300770Sdim    __thread_struct(const __thread_struct&);
128300770Sdim    __thread_struct& operator=(const __thread_struct&);
129300770Sdimpublic:
130300770Sdim    __thread_struct();
131300770Sdim    ~__thread_struct();
132300770Sdim
133300770Sdim    void notify_all_at_thread_exit(condition_variable*, mutex*);
134300770Sdim    void __make_ready_at_thread_exit(__assoc_sub_state*);
135300770Sdim};
136300770Sdim
137227825Stheraventemplate <class _Tp>
138227825Stheravenclass __thread_specific_ptr
139227825Stheraven{
140227825Stheraven    pthread_key_t __key_;
141227825Stheraven
142300770Sdim     // Only __thread_local_data() may construct a __thread_specific_ptr
143300770Sdim     // and only with _Tp == __thread_struct.
144300770Sdim    static_assert((is_same<_Tp, __thread_struct>::value), "");
145300770Sdim    __thread_specific_ptr();
146300770Sdim    friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
147300770Sdim
148227825Stheraven    __thread_specific_ptr(const __thread_specific_ptr&);
149227825Stheraven    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
150227825Stheraven
151227825Stheraven    static void __at_thread_exit(void*);
152227825Stheravenpublic:
153227825Stheraven    typedef _Tp* pointer;
154227825Stheraven
155227825Stheraven    ~__thread_specific_ptr();
156227825Stheraven
157227825Stheraven    _LIBCPP_INLINE_VISIBILITY
158227825Stheraven    pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));}
159227825Stheraven    _LIBCPP_INLINE_VISIBILITY
160227825Stheraven    pointer operator*() const {return *get();}
161227825Stheraven    _LIBCPP_INLINE_VISIBILITY
162227825Stheraven    pointer operator->() const {return get();}
163227825Stheraven    pointer release();
164227825Stheraven    void reset(pointer __p = nullptr);
165227825Stheraven};
166227825Stheraven
167227825Stheraventemplate <class _Tp>
168227825Stheravenvoid
169227825Stheraven__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
170227825Stheraven{
171227825Stheraven    delete static_cast<pointer>(__p);
172227825Stheraven}
173227825Stheraven
174227825Stheraventemplate <class _Tp>
175227825Stheraven__thread_specific_ptr<_Tp>::__thread_specific_ptr()
176227825Stheraven{
177227825Stheraven    int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
178249989Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
179227825Stheraven    if (__ec)
180227825Stheraven        throw system_error(error_code(__ec, system_category()),
181227825Stheraven                           "__thread_specific_ptr construction failed");
182249989Sdim#endif
183227825Stheraven}
184227825Stheraven
185227825Stheraventemplate <class _Tp>
186227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
187227825Stheraven{
188300770Sdim    // __thread_specific_ptr is only created with a static storage duration
189300770Sdim    // so this destructor is only invoked during program termination. Invoking
190300770Sdim    // pthread_key_delete(__key_) may prevent other threads from deleting their
191300770Sdim    // thread local data. For this reason we leak the key.
192227825Stheraven}
193227825Stheraven
194227825Stheraventemplate <class _Tp>
195227825Stheraventypename __thread_specific_ptr<_Tp>::pointer
196227825Stheraven__thread_specific_ptr<_Tp>::release()
197227825Stheraven{
198227825Stheraven    pointer __p = get();
199227825Stheraven    pthread_setspecific(__key_, 0);
200227825Stheraven    return __p;
201227825Stheraven}
202227825Stheraven
203227825Stheraventemplate <class _Tp>
204227825Stheravenvoid
205227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p)
206227825Stheraven{
207227825Stheraven    pointer __p_old = get();
208227825Stheraven    pthread_setspecific(__key_, __p);
209227825Stheraven    delete __p_old;
210227825Stheraven}
211227825Stheraven
212249989Sdimclass _LIBCPP_TYPE_VIS thread;
213249989Sdimclass _LIBCPP_TYPE_VIS __thread_id;
214227825Stheraven
215227825Stheravennamespace this_thread
216227825Stheraven{
217227825Stheraven
218241900Sdim_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
219227825Stheraven
220227825Stheraven}  // this_thread
221227825Stheraven
222261272Sdimtemplate<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
223232924Stheraven
224261272Sdimclass _LIBCPP_TYPE_VIS_ONLY __thread_id
225227825Stheraven{
226227825Stheraven    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
227227825Stheraven    // NULL is the no-thread value on Darwin.  Someone needs to check
228227825Stheraven    // on other platforms.  We assume 0 works everywhere for now.
229227825Stheraven    pthread_t __id_;
230227825Stheraven
231227825Stheravenpublic:
232227825Stheraven    _LIBCPP_INLINE_VISIBILITY
233241900Sdim    __thread_id() _NOEXCEPT : __id_(0) {}
234227825Stheraven
235227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
236241900Sdim        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
237227825Stheraven        {return __x.__id_ == __y.__id_;}
238227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
239241900Sdim        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
240227825Stheraven        {return !(__x == __y);}
241227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
242241900Sdim        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
243227825Stheraven        {return __x.__id_ < __y.__id_;}
244227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
245241900Sdim        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
246227825Stheraven        {return !(__y < __x);}
247227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
248241900Sdim        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
249227825Stheraven        {return   __y < __x ;}
250227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
251241900Sdim        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
252227825Stheraven        {return !(__x < __y);}
253227825Stheraven
254227825Stheraven    template<class _CharT, class _Traits>
255227825Stheraven    friend
256227825Stheraven    _LIBCPP_INLINE_VISIBILITY
257227825Stheraven    basic_ostream<_CharT, _Traits>&
258227825Stheraven    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
259227825Stheraven        {return __os << __id.__id_;}
260227825Stheraven
261227825Stheravenprivate:
262227825Stheraven    _LIBCPP_INLINE_VISIBILITY
263227825Stheraven    __thread_id(pthread_t __id) : __id_(__id) {}
264227825Stheraven
265241900Sdim    friend __thread_id this_thread::get_id() _NOEXCEPT;
266249989Sdim    friend class _LIBCPP_TYPE_VIS thread;
267261272Sdim    friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
268227825Stheraven};
269227825Stheraven
270227825Stheraventemplate<>
271261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>
272227825Stheraven    : public unary_function<__thread_id, size_t>
273227825Stheraven{
274227825Stheraven    _LIBCPP_INLINE_VISIBILITY
275227825Stheraven    size_t operator()(__thread_id __v) const
276227825Stheraven    {
277232924Stheraven        return hash<pthread_t>()(__v.__id_);
278227825Stheraven    }
279227825Stheraven};
280227825Stheraven
281227825Stheravennamespace this_thread
282227825Stheraven{
283227825Stheraven
284227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
285227825Stheraven__thread_id
286241900Sdimget_id() _NOEXCEPT
287227825Stheraven{
288227825Stheraven    return pthread_self();
289227825Stheraven}
290227825Stheraven
291227825Stheraven}  // this_thread
292227825Stheraven
293249989Sdimclass _LIBCPP_TYPE_VIS thread
294227825Stheraven{
295227825Stheraven    pthread_t __t_;
296227825Stheraven
297227825Stheraven    thread(const thread&);
298227825Stheraven    thread& operator=(const thread&);
299227825Stheravenpublic:
300227825Stheraven    typedef __thread_id id;
301227825Stheraven    typedef pthread_t native_handle_type;
302227825Stheraven
303227825Stheraven    _LIBCPP_INLINE_VISIBILITY
304241900Sdim    thread() _NOEXCEPT : __t_(0) {}
305227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
306232924Stheraven    template <class _Fp, class ..._Args,
307227825Stheraven              class = typename enable_if
308227825Stheraven              <
309232924Stheraven                   !is_same<typename decay<_Fp>::type, thread>::value
310227825Stheraven              >::type
311227825Stheraven             >
312232924Stheraven        explicit thread(_Fp&& __f, _Args&&... __args);
313227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
314232924Stheraven    template <class _Fp> explicit thread(_Fp __f);
315227825Stheraven#endif
316227825Stheraven    ~thread();
317227825Stheraven
318227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
319227825Stheraven    _LIBCPP_INLINE_VISIBILITY
320241900Sdim    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;}
321300770Sdim    _LIBCPP_INLINE_VISIBILITY
322241900Sdim    thread& operator=(thread&& __t) _NOEXCEPT;
323227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
324227825Stheraven
325227825Stheraven    _LIBCPP_INLINE_VISIBILITY
326241900Sdim    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
327227825Stheraven
328227825Stheraven    _LIBCPP_INLINE_VISIBILITY
329241900Sdim    bool joinable() const _NOEXCEPT {return __t_ != 0;}
330227825Stheraven    void join();
331227825Stheraven    void detach();
332227825Stheraven    _LIBCPP_INLINE_VISIBILITY
333241900Sdim    id get_id() const _NOEXCEPT {return __t_;}
334227825Stheraven    _LIBCPP_INLINE_VISIBILITY
335241900Sdim    native_handle_type native_handle() _NOEXCEPT {return __t_;}
336227825Stheraven
337241900Sdim    static unsigned hardware_concurrency() _NOEXCEPT;
338227825Stheraven};
339227825Stheraven
340227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
341227825Stheraven
342232924Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices>
343227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
344227825Stheravenvoid
345249989Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
346227825Stheraven{
347227825Stheraven    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
348227825Stheraven}
349227825Stheraven
350232924Stheraventemplate <class _Fp>
351227825Stheravenvoid*
352227825Stheraven__thread_proxy(void* __vp)
353227825Stheraven{
354227825Stheraven    __thread_local_data().reset(new __thread_struct);
355232924Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
356232924Stheraven    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
357249989Sdim    __thread_execute(*__p, _Index());
358227825Stheraven    return nullptr;
359227825Stheraven}
360227825Stheraven
361232924Stheraventemplate <class _Fp, class ..._Args,
362227825Stheraven          class
363227825Stheraven         >
364232924Stheraventhread::thread(_Fp&& __f, _Args&&... __args)
365227825Stheraven{
366232924Stheraven    typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
367232924Stheraven    _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)),
368227825Stheraven                                __decay_copy(_VSTD::forward<_Args>(__args))...));
369232924Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
370227825Stheraven    if (__ec == 0)
371227825Stheraven        __p.release();
372227825Stheraven    else
373227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
374227825Stheraven}
375227825Stheraven
376227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
377227825Stheraven
378232924Stheraventemplate <class _Fp>
379227825Stheravenvoid*
380227825Stheraven__thread_proxy(void* __vp)
381227825Stheraven{
382227825Stheraven    __thread_local_data().reset(new __thread_struct);
383232924Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
384227825Stheraven    (*__p)();
385227825Stheraven    return nullptr;
386227825Stheraven}
387227825Stheraven
388232924Stheraventemplate <class _Fp>
389232924Stheraventhread::thread(_Fp __f)
390227825Stheraven{
391232924Stheraven    std::unique_ptr<_Fp> __p(new _Fp(__f));
392232924Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get());
393227825Stheraven    if (__ec == 0)
394227825Stheraven        __p.release();
395227825Stheraven    else
396227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
397227825Stheraven}
398227825Stheraven
399227825Stheraven#endif  // _LIBCPP_HAS_NO_VARIADICS
400227825Stheraven
401227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
402227825Stheraven
403300770Sdiminline
404227825Stheraventhread&
405241900Sdimthread::operator=(thread&& __t) _NOEXCEPT
406227825Stheraven{
407227825Stheraven    if (__t_ != 0)
408227825Stheraven        terminate();
409227825Stheraven    __t_ = __t.__t_;
410227825Stheraven    __t.__t_ = 0;
411227825Stheraven    return *this;
412227825Stheraven}
413227825Stheraven
414227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
415227825Stheraven
416227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
417241900Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
418227825Stheraven
419227825Stheravennamespace this_thread
420227825Stheraven{
421227825Stheraven
422261272Sdim_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns);
423227825Stheraven
424227825Stheraventemplate <class _Rep, class _Period>
425227825Stheravenvoid
426227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d)
427227825Stheraven{
428227825Stheraven    using namespace chrono;
429241900Sdim    if (__d > duration<_Rep, _Period>::zero())
430241900Sdim    {
431241900Sdim        _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
432241900Sdim        nanoseconds __ns;
433241900Sdim        if (__d < _Max)
434241900Sdim        {
435241900Sdim            __ns = duration_cast<nanoseconds>(__d);
436241900Sdim            if (__ns < __d)
437241900Sdim                ++__ns;
438241900Sdim        }
439241900Sdim        else
440241900Sdim            __ns = nanoseconds::max();
441241900Sdim        sleep_for(__ns);
442241900Sdim    }
443227825Stheraven}
444227825Stheraven
445227825Stheraventemplate <class _Clock, class _Duration>
446227825Stheravenvoid
447227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t)
448227825Stheraven{
449227825Stheraven    using namespace chrono;
450227825Stheraven    mutex __mut;
451227825Stheraven    condition_variable __cv;
452227825Stheraven    unique_lock<mutex> __lk(__mut);
453227825Stheraven    while (_Clock::now() < __t)
454227825Stheraven        __cv.wait_until(__lk, __t);
455227825Stheraven}
456227825Stheraven
457227825Stheraventemplate <class _Duration>
458227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
459227825Stheravenvoid
460227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
461227825Stheraven{
462227825Stheraven    using namespace chrono;
463227825Stheraven    sleep_for(__t - steady_clock::now());
464227825Stheraven}
465227825Stheraven
466227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
467241900Sdimvoid yield() _NOEXCEPT {sched_yield();}
468227825Stheraven
469227825Stheraven}  // this_thread
470227825Stheraven
471227825Stheraven_LIBCPP_END_NAMESPACE_STD
472227825Stheraven
473276792Sdim#endif // !_LIBCPP_HAS_NO_THREADS
474276792Sdim
475227825Stheraven#endif  // _LIBCPP_THREAD
476