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
29241903Sdim    thread() noexcept;
30227825Stheraven    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
31227825Stheraven    ~thread();
32227825Stheraven
33227825Stheraven    thread(const thread&) = delete;
34241903Sdim    thread(thread&& t) noexcept;
35227825Stheraven
36227825Stheraven    thread& operator=(const thread&) = delete;
37241903Sdim    thread& operator=(thread&& t) noexcept;
38227825Stheraven
39241903Sdim    void swap(thread& t) noexcept;
40227825Stheraven
41241903Sdim    bool joinable() const noexcept;
42227825Stheraven    void join();
43227825Stheraven    void detach();
44241903Sdim    id get_id() const noexcept;
45227825Stheraven    native_handle_type native_handle();
46227825Stheraven
47241903Sdim    static unsigned hardware_concurrency() noexcept;
48227825Stheraven};
49227825Stheraven
50241903Sdimvoid swap(thread& x, thread& y) noexcept;
51227825Stheraven
52227825Stheravenclass thread::id
53227825Stheraven{
54227825Stheravenpublic:
55241903Sdim    id() noexcept;
56227825Stheraven};
57227825Stheraven
58241903Sdimbool operator==(thread::id x, thread::id y) noexcept;
59241903Sdimbool operator!=(thread::id x, thread::id y) noexcept;
60241903Sdimbool operator< (thread::id x, thread::id y) noexcept;
61241903Sdimbool operator<=(thread::id x, thread::id y) noexcept;
62241903Sdimbool operator> (thread::id x, thread::id y) noexcept;
63241903Sdimbool 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
72241903Sdimthread::id get_id() noexcept;
73227825Stheraven
74241903Sdimvoid 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>
102278724Sdim#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
110278724Sdim#ifdef _LIBCPP_HAS_NO_THREADS
111278724Sdim#error <thread> is not supported on this single threaded system
112278724Sdim#else // !_LIBCPP_HAS_NO_THREADS
113278724Sdim
114227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
115227825Stheraven
116227825Stheraventemplate <class _Tp>
117227825Stheravenclass __thread_specific_ptr
118227825Stheraven{
119227825Stheraven    pthread_key_t __key_;
120227825Stheraven
121227825Stheraven    __thread_specific_ptr(const __thread_specific_ptr&);
122227825Stheraven    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
123227825Stheraven
124227825Stheraven    static void __at_thread_exit(void*);
125227825Stheravenpublic:
126227825Stheraven    typedef _Tp* pointer;
127227825Stheraven
128227825Stheraven    __thread_specific_ptr();
129227825Stheraven    ~__thread_specific_ptr();
130227825Stheraven
131227825Stheraven    _LIBCPP_INLINE_VISIBILITY
132227825Stheraven    pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));}
133227825Stheraven    _LIBCPP_INLINE_VISIBILITY
134227825Stheraven    pointer operator*() const {return *get();}
135227825Stheraven    _LIBCPP_INLINE_VISIBILITY
136227825Stheraven    pointer operator->() const {return get();}
137227825Stheraven    pointer release();
138227825Stheraven    void reset(pointer __p = nullptr);
139227825Stheraven};
140227825Stheraven
141227825Stheraventemplate <class _Tp>
142227825Stheravenvoid
143227825Stheraven__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
144227825Stheraven{
145227825Stheraven    delete static_cast<pointer>(__p);
146227825Stheraven}
147227825Stheraven
148227825Stheraventemplate <class _Tp>
149227825Stheraven__thread_specific_ptr<_Tp>::__thread_specific_ptr()
150227825Stheraven{
151227825Stheraven    int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
152249998Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
153227825Stheraven    if (__ec)
154227825Stheraven        throw system_error(error_code(__ec, system_category()),
155227825Stheraven                           "__thread_specific_ptr construction failed");
156249998Sdim#endif
157227825Stheraven}
158227825Stheraven
159227825Stheraventemplate <class _Tp>
160227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
161227825Stheraven{
162227825Stheraven    pthread_key_delete(__key_);
163227825Stheraven}
164227825Stheraven
165227825Stheraventemplate <class _Tp>
166227825Stheraventypename __thread_specific_ptr<_Tp>::pointer
167227825Stheraven__thread_specific_ptr<_Tp>::release()
168227825Stheraven{
169227825Stheraven    pointer __p = get();
170227825Stheraven    pthread_setspecific(__key_, 0);
171227825Stheraven    return __p;
172227825Stheraven}
173227825Stheraven
174227825Stheraventemplate <class _Tp>
175227825Stheravenvoid
176227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p)
177227825Stheraven{
178227825Stheraven    pointer __p_old = get();
179227825Stheraven    pthread_setspecific(__key_, __p);
180227825Stheraven    delete __p_old;
181227825Stheraven}
182227825Stheraven
183249998Sdimclass _LIBCPP_TYPE_VIS thread;
184249998Sdimclass _LIBCPP_TYPE_VIS __thread_id;
185227825Stheraven
186227825Stheravennamespace this_thread
187227825Stheraven{
188227825Stheraven
189241903Sdim_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
190227825Stheraven
191227825Stheraven}  // this_thread
192227825Stheraven
193262801Sdimtemplate<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
194232950Stheraven
195262801Sdimclass _LIBCPP_TYPE_VIS_ONLY __thread_id
196227825Stheraven{
197227825Stheraven    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
198227825Stheraven    // NULL is the no-thread value on Darwin.  Someone needs to check
199227825Stheraven    // on other platforms.  We assume 0 works everywhere for now.
200227825Stheraven    pthread_t __id_;
201227825Stheraven
202227825Stheravenpublic:
203227825Stheraven    _LIBCPP_INLINE_VISIBILITY
204241903Sdim    __thread_id() _NOEXCEPT : __id_(0) {}
205227825Stheraven
206227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
207241903Sdim        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
208227825Stheraven        {return __x.__id_ == __y.__id_;}
209227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
210241903Sdim        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
211227825Stheraven        {return !(__x == __y);}
212227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
213241903Sdim        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
214227825Stheraven        {return __x.__id_ < __y.__id_;}
215227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
216241903Sdim        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
217227825Stheraven        {return !(__y < __x);}
218227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
219241903Sdim        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
220227825Stheraven        {return   __y < __x ;}
221227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
222241903Sdim        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
223227825Stheraven        {return !(__x < __y);}
224227825Stheraven
225227825Stheraven    template<class _CharT, class _Traits>
226227825Stheraven    friend
227227825Stheraven    _LIBCPP_INLINE_VISIBILITY
228227825Stheraven    basic_ostream<_CharT, _Traits>&
229227825Stheraven    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
230227825Stheraven        {return __os << __id.__id_;}
231227825Stheraven
232227825Stheravenprivate:
233227825Stheraven    _LIBCPP_INLINE_VISIBILITY
234227825Stheraven    __thread_id(pthread_t __id) : __id_(__id) {}
235227825Stheraven
236241903Sdim    friend __thread_id this_thread::get_id() _NOEXCEPT;
237249998Sdim    friend class _LIBCPP_TYPE_VIS thread;
238262801Sdim    friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
239227825Stheraven};
240227825Stheraven
241227825Stheraventemplate<>
242262801Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>
243227825Stheraven    : public unary_function<__thread_id, size_t>
244227825Stheraven{
245227825Stheraven    _LIBCPP_INLINE_VISIBILITY
246227825Stheraven    size_t operator()(__thread_id __v) const
247227825Stheraven    {
248232950Stheraven        return hash<pthread_t>()(__v.__id_);
249227825Stheraven    }
250227825Stheraven};
251227825Stheraven
252227825Stheravennamespace this_thread
253227825Stheraven{
254227825Stheraven
255227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
256227825Stheraven__thread_id
257241903Sdimget_id() _NOEXCEPT
258227825Stheraven{
259227825Stheraven    return pthread_self();
260227825Stheraven}
261227825Stheraven
262227825Stheraven}  // this_thread
263227825Stheraven
264249998Sdimclass _LIBCPP_TYPE_VIS thread
265227825Stheraven{
266227825Stheraven    pthread_t __t_;
267227825Stheraven
268227825Stheraven    thread(const thread&);
269227825Stheraven    thread& operator=(const thread&);
270227825Stheravenpublic:
271227825Stheraven    typedef __thread_id id;
272227825Stheraven    typedef pthread_t native_handle_type;
273227825Stheraven
274227825Stheraven    _LIBCPP_INLINE_VISIBILITY
275241903Sdim    thread() _NOEXCEPT : __t_(0) {}
276227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
277232950Stheraven    template <class _Fp, class ..._Args,
278227825Stheraven              class = typename enable_if
279227825Stheraven              <
280232950Stheraven                   !is_same<typename decay<_Fp>::type, thread>::value
281227825Stheraven              >::type
282227825Stheraven             >
283232950Stheraven        explicit thread(_Fp&& __f, _Args&&... __args);
284227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
285232950Stheraven    template <class _Fp> explicit thread(_Fp __f);
286227825Stheraven#endif
287227825Stheraven    ~thread();
288227825Stheraven
289227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
290227825Stheraven    _LIBCPP_INLINE_VISIBILITY
291241903Sdim    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;}
292241903Sdim    thread& operator=(thread&& __t) _NOEXCEPT;
293227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
294227825Stheraven
295227825Stheraven    _LIBCPP_INLINE_VISIBILITY
296241903Sdim    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
297227825Stheraven
298227825Stheraven    _LIBCPP_INLINE_VISIBILITY
299241903Sdim    bool joinable() const _NOEXCEPT {return __t_ != 0;}
300227825Stheraven    void join();
301227825Stheraven    void detach();
302227825Stheraven    _LIBCPP_INLINE_VISIBILITY
303241903Sdim    id get_id() const _NOEXCEPT {return __t_;}
304227825Stheraven    _LIBCPP_INLINE_VISIBILITY
305241903Sdim    native_handle_type native_handle() _NOEXCEPT {return __t_;}
306227825Stheraven
307241903Sdim    static unsigned hardware_concurrency() _NOEXCEPT;
308227825Stheraven};
309227825Stheraven
310227825Stheravenclass __assoc_sub_state;
311227825Stheraven
312227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp;
313227825Stheraven
314262801Sdimclass _LIBCPP_TYPE_VIS __thread_struct
315227825Stheraven{
316227825Stheraven    __thread_struct_imp* __p_;
317227825Stheraven
318227825Stheraven    __thread_struct(const __thread_struct&);
319227825Stheraven    __thread_struct& operator=(const __thread_struct&);
320227825Stheravenpublic:
321227825Stheraven    __thread_struct();
322227825Stheraven    ~__thread_struct();
323227825Stheraven
324227825Stheraven    void notify_all_at_thread_exit(condition_variable*, mutex*);
325227825Stheraven    void __make_ready_at_thread_exit(__assoc_sub_state*);
326227825Stheraven};
327227825Stheraven
328262801Sdim_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
329227825Stheraven
330227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
331227825Stheraven
332232950Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices>
333227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
334227825Stheravenvoid
335249998Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
336227825Stheraven{
337227825Stheraven    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
338227825Stheraven}
339227825Stheraven
340232950Stheraventemplate <class _Fp>
341227825Stheravenvoid*
342227825Stheraven__thread_proxy(void* __vp)
343227825Stheraven{
344227825Stheraven    __thread_local_data().reset(new __thread_struct);
345232950Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
346232950Stheraven    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
347249998Sdim    __thread_execute(*__p, _Index());
348227825Stheraven    return nullptr;
349227825Stheraven}
350227825Stheraven
351232950Stheraventemplate <class _Fp, class ..._Args,
352227825Stheraven          class
353227825Stheraven         >
354232950Stheraventhread::thread(_Fp&& __f, _Args&&... __args)
355227825Stheraven{
356232950Stheraven    typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
357232950Stheraven    _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)),
358227825Stheraven                                __decay_copy(_VSTD::forward<_Args>(__args))...));
359232950Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
360227825Stheraven    if (__ec == 0)
361227825Stheraven        __p.release();
362227825Stheraven    else
363227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
364227825Stheraven}
365227825Stheraven
366227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
367227825Stheraven
368232950Stheraventemplate <class _Fp>
369227825Stheravenvoid*
370227825Stheraven__thread_proxy(void* __vp)
371227825Stheraven{
372227825Stheraven    __thread_local_data().reset(new __thread_struct);
373232950Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
374227825Stheraven    (*__p)();
375227825Stheraven    return nullptr;
376227825Stheraven}
377227825Stheraven
378232950Stheraventemplate <class _Fp>
379232950Stheraventhread::thread(_Fp __f)
380227825Stheraven{
381232950Stheraven    std::unique_ptr<_Fp> __p(new _Fp(__f));
382232950Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get());
383227825Stheraven    if (__ec == 0)
384227825Stheraven        __p.release();
385227825Stheraven    else
386227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
387227825Stheraven}
388227825Stheraven
389227825Stheraven#endif  // _LIBCPP_HAS_NO_VARIADICS
390227825Stheraven
391227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
392227825Stheraven
393227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
394227825Stheraventhread&
395241903Sdimthread::operator=(thread&& __t) _NOEXCEPT
396227825Stheraven{
397227825Stheraven    if (__t_ != 0)
398227825Stheraven        terminate();
399227825Stheraven    __t_ = __t.__t_;
400227825Stheraven    __t.__t_ = 0;
401227825Stheraven    return *this;
402227825Stheraven}
403227825Stheraven
404227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
405227825Stheraven
406227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
407241903Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
408227825Stheraven
409227825Stheravennamespace this_thread
410227825Stheraven{
411227825Stheraven
412262801Sdim_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns);
413227825Stheraven
414227825Stheraventemplate <class _Rep, class _Period>
415227825Stheravenvoid
416227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d)
417227825Stheraven{
418227825Stheraven    using namespace chrono;
419241903Sdim    if (__d > duration<_Rep, _Period>::zero())
420241903Sdim    {
421241903Sdim        _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
422241903Sdim        nanoseconds __ns;
423241903Sdim        if (__d < _Max)
424241903Sdim        {
425241903Sdim            __ns = duration_cast<nanoseconds>(__d);
426241903Sdim            if (__ns < __d)
427241903Sdim                ++__ns;
428241903Sdim        }
429241903Sdim        else
430241903Sdim            __ns = nanoseconds::max();
431241903Sdim        sleep_for(__ns);
432241903Sdim    }
433227825Stheraven}
434227825Stheraven
435227825Stheraventemplate <class _Clock, class _Duration>
436227825Stheravenvoid
437227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t)
438227825Stheraven{
439227825Stheraven    using namespace chrono;
440227825Stheraven    mutex __mut;
441227825Stheraven    condition_variable __cv;
442227825Stheraven    unique_lock<mutex> __lk(__mut);
443227825Stheraven    while (_Clock::now() < __t)
444227825Stheraven        __cv.wait_until(__lk, __t);
445227825Stheraven}
446227825Stheraven
447227825Stheraventemplate <class _Duration>
448227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
449227825Stheravenvoid
450227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
451227825Stheraven{
452227825Stheraven    using namespace chrono;
453227825Stheraven    sleep_for(__t - steady_clock::now());
454227825Stheraven}
455227825Stheraven
456227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
457241903Sdimvoid yield() _NOEXCEPT {sched_yield();}
458227825Stheraven
459227825Stheraven}  // this_thread
460227825Stheraven
461227825Stheraven_LIBCPP_END_NAMESPACE_STD
462227825Stheraven
463278724Sdim#endif // !_LIBCPP_HAS_NO_THREADS
464278724Sdim
465227825Stheraven#endif  // _LIBCPP_THREAD
466