thread revision 261272
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
188261272Sdimtemplate<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
189232924Stheraven
190261272Sdimclass _LIBCPP_TYPE_VIS_ONLY __thread_id
191227825Stheraven{
192227825Stheraven    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
193227825Stheraven    // NULL is the no-thread value on Darwin.  Someone needs to check
194227825Stheraven    // on other platforms.  We assume 0 works everywhere for now.
195227825Stheraven    pthread_t __id_;
196227825Stheraven
197227825Stheravenpublic:
198227825Stheraven    _LIBCPP_INLINE_VISIBILITY
199241900Sdim    __thread_id() _NOEXCEPT : __id_(0) {}
200227825Stheraven
201227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
202241900Sdim        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
203227825Stheraven        {return __x.__id_ == __y.__id_;}
204227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
205241900Sdim        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
206227825Stheraven        {return !(__x == __y);}
207227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
208241900Sdim        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
209227825Stheraven        {return __x.__id_ < __y.__id_;}
210227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
211241900Sdim        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
212227825Stheraven        {return !(__y < __x);}
213227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
214241900Sdim        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
215227825Stheraven        {return   __y < __x ;}
216227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
217241900Sdim        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
218227825Stheraven        {return !(__x < __y);}
219227825Stheraven
220227825Stheraven    template<class _CharT, class _Traits>
221227825Stheraven    friend
222227825Stheraven    _LIBCPP_INLINE_VISIBILITY
223227825Stheraven    basic_ostream<_CharT, _Traits>&
224227825Stheraven    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
225227825Stheraven        {return __os << __id.__id_;}
226227825Stheraven
227227825Stheravenprivate:
228227825Stheraven    _LIBCPP_INLINE_VISIBILITY
229227825Stheraven    __thread_id(pthread_t __id) : __id_(__id) {}
230227825Stheraven
231241900Sdim    friend __thread_id this_thread::get_id() _NOEXCEPT;
232249989Sdim    friend class _LIBCPP_TYPE_VIS thread;
233261272Sdim    friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
234227825Stheraven};
235227825Stheraven
236227825Stheraventemplate<>
237261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>
238227825Stheraven    : public unary_function<__thread_id, size_t>
239227825Stheraven{
240227825Stheraven    _LIBCPP_INLINE_VISIBILITY
241227825Stheraven    size_t operator()(__thread_id __v) const
242227825Stheraven    {
243232924Stheraven        return hash<pthread_t>()(__v.__id_);
244227825Stheraven    }
245227825Stheraven};
246227825Stheraven
247227825Stheravennamespace this_thread
248227825Stheraven{
249227825Stheraven
250227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
251227825Stheraven__thread_id
252241900Sdimget_id() _NOEXCEPT
253227825Stheraven{
254227825Stheraven    return pthread_self();
255227825Stheraven}
256227825Stheraven
257227825Stheraven}  // this_thread
258227825Stheraven
259249989Sdimclass _LIBCPP_TYPE_VIS thread
260227825Stheraven{
261227825Stheraven    pthread_t __t_;
262227825Stheraven
263227825Stheraven    thread(const thread&);
264227825Stheraven    thread& operator=(const thread&);
265227825Stheravenpublic:
266227825Stheraven    typedef __thread_id id;
267227825Stheraven    typedef pthread_t native_handle_type;
268227825Stheraven
269227825Stheraven    _LIBCPP_INLINE_VISIBILITY
270241900Sdim    thread() _NOEXCEPT : __t_(0) {}
271227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
272232924Stheraven    template <class _Fp, class ..._Args,
273227825Stheraven              class = typename enable_if
274227825Stheraven              <
275232924Stheraven                   !is_same<typename decay<_Fp>::type, thread>::value
276227825Stheraven              >::type
277227825Stheraven             >
278232924Stheraven        explicit thread(_Fp&& __f, _Args&&... __args);
279227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
280232924Stheraven    template <class _Fp> explicit thread(_Fp __f);
281227825Stheraven#endif
282227825Stheraven    ~thread();
283227825Stheraven
284227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
285227825Stheraven    _LIBCPP_INLINE_VISIBILITY
286241900Sdim    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;}
287241900Sdim    thread& operator=(thread&& __t) _NOEXCEPT;
288227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
289227825Stheraven
290227825Stheraven    _LIBCPP_INLINE_VISIBILITY
291241900Sdim    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
292227825Stheraven
293227825Stheraven    _LIBCPP_INLINE_VISIBILITY
294241900Sdim    bool joinable() const _NOEXCEPT {return __t_ != 0;}
295227825Stheraven    void join();
296227825Stheraven    void detach();
297227825Stheraven    _LIBCPP_INLINE_VISIBILITY
298241900Sdim    id get_id() const _NOEXCEPT {return __t_;}
299227825Stheraven    _LIBCPP_INLINE_VISIBILITY
300241900Sdim    native_handle_type native_handle() _NOEXCEPT {return __t_;}
301227825Stheraven
302241900Sdim    static unsigned hardware_concurrency() _NOEXCEPT;
303227825Stheraven};
304227825Stheraven
305227825Stheravenclass __assoc_sub_state;
306227825Stheraven
307227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp;
308227825Stheraven
309261272Sdimclass _LIBCPP_TYPE_VIS __thread_struct
310227825Stheraven{
311227825Stheraven    __thread_struct_imp* __p_;
312227825Stheraven
313227825Stheraven    __thread_struct(const __thread_struct&);
314227825Stheraven    __thread_struct& operator=(const __thread_struct&);
315227825Stheravenpublic:
316227825Stheraven    __thread_struct();
317227825Stheraven    ~__thread_struct();
318227825Stheraven
319227825Stheraven    void notify_all_at_thread_exit(condition_variable*, mutex*);
320227825Stheraven    void __make_ready_at_thread_exit(__assoc_sub_state*);
321227825Stheraven};
322227825Stheraven
323261272Sdim_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
324227825Stheraven
325227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS
326227825Stheraven
327232924Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices>
328227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
329227825Stheravenvoid
330249989Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
331227825Stheraven{
332227825Stheraven    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
333227825Stheraven}
334227825Stheraven
335232924Stheraventemplate <class _Fp>
336227825Stheravenvoid*
337227825Stheraven__thread_proxy(void* __vp)
338227825Stheraven{
339227825Stheraven    __thread_local_data().reset(new __thread_struct);
340232924Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
341232924Stheraven    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
342249989Sdim    __thread_execute(*__p, _Index());
343227825Stheraven    return nullptr;
344227825Stheraven}
345227825Stheraven
346232924Stheraventemplate <class _Fp, class ..._Args,
347227825Stheraven          class
348227825Stheraven         >
349232924Stheraventhread::thread(_Fp&& __f, _Args&&... __args)
350227825Stheraven{
351232924Stheraven    typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
352232924Stheraven    _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)),
353227825Stheraven                                __decay_copy(_VSTD::forward<_Args>(__args))...));
354232924Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
355227825Stheraven    if (__ec == 0)
356227825Stheraven        __p.release();
357227825Stheraven    else
358227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
359227825Stheraven}
360227825Stheraven
361227825Stheraven#else  // _LIBCPP_HAS_NO_VARIADICS
362227825Stheraven
363232924Stheraventemplate <class _Fp>
364227825Stheravenvoid*
365227825Stheraven__thread_proxy(void* __vp)
366227825Stheraven{
367227825Stheraven    __thread_local_data().reset(new __thread_struct);
368232924Stheraven    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
369227825Stheraven    (*__p)();
370227825Stheraven    return nullptr;
371227825Stheraven}
372227825Stheraven
373232924Stheraventemplate <class _Fp>
374232924Stheraventhread::thread(_Fp __f)
375227825Stheraven{
376232924Stheraven    std::unique_ptr<_Fp> __p(new _Fp(__f));
377232924Stheraven    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get());
378227825Stheraven    if (__ec == 0)
379227825Stheraven        __p.release();
380227825Stheraven    else
381227825Stheraven        __throw_system_error(__ec, "thread constructor failed");
382227825Stheraven}
383227825Stheraven
384227825Stheraven#endif  // _LIBCPP_HAS_NO_VARIADICS
385227825Stheraven
386227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
387227825Stheraven
388227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
389227825Stheraventhread&
390241900Sdimthread::operator=(thread&& __t) _NOEXCEPT
391227825Stheraven{
392227825Stheraven    if (__t_ != 0)
393227825Stheraven        terminate();
394227825Stheraven    __t_ = __t.__t_;
395227825Stheraven    __t.__t_ = 0;
396227825Stheraven    return *this;
397227825Stheraven}
398227825Stheraven
399227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
400227825Stheraven
401227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
402241900Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
403227825Stheraven
404227825Stheravennamespace this_thread
405227825Stheraven{
406227825Stheraven
407261272Sdim_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns);
408227825Stheraven
409227825Stheraventemplate <class _Rep, class _Period>
410227825Stheravenvoid
411227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d)
412227825Stheraven{
413227825Stheraven    using namespace chrono;
414241900Sdim    if (__d > duration<_Rep, _Period>::zero())
415241900Sdim    {
416241900Sdim        _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
417241900Sdim        nanoseconds __ns;
418241900Sdim        if (__d < _Max)
419241900Sdim        {
420241900Sdim            __ns = duration_cast<nanoseconds>(__d);
421241900Sdim            if (__ns < __d)
422241900Sdim                ++__ns;
423241900Sdim        }
424241900Sdim        else
425241900Sdim            __ns = nanoseconds::max();
426241900Sdim        sleep_for(__ns);
427241900Sdim    }
428227825Stheraven}
429227825Stheraven
430227825Stheraventemplate <class _Clock, class _Duration>
431227825Stheravenvoid
432227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t)
433227825Stheraven{
434227825Stheraven    using namespace chrono;
435227825Stheraven    mutex __mut;
436227825Stheraven    condition_variable __cv;
437227825Stheraven    unique_lock<mutex> __lk(__mut);
438227825Stheraven    while (_Clock::now() < __t)
439227825Stheraven        __cv.wait_until(__lk, __t);
440227825Stheraven}
441227825Stheraven
442227825Stheraventemplate <class _Duration>
443227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
444227825Stheravenvoid
445227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
446227825Stheraven{
447227825Stheraven    using namespace chrono;
448227825Stheraven    sleep_for(__t - steady_clock::now());
449227825Stheraven}
450227825Stheraven
451227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
452241900Sdimvoid yield() _NOEXCEPT {sched_yield();}
453227825Stheraven
454227825Stheraven}  // this_thread
455227825Stheraven
456227825Stheraven_LIBCPP_END_NAMESPACE_STD
457227825Stheraven
458227825Stheraven#endif  // _LIBCPP_THREAD
459