Home | History | Annotate | Download | only in include
      1 // -*- C++ -*-
      2 //===--------------------------- thread -----------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_THREAD
     12 #define _LIBCPP_THREAD
     13 
     14 /*
     15 
     16     thread synopsis
     17 
     18 #define __STDCPP_THREADS__ __cplusplus
     19 
     20 namespace std
     21 {
     22 
     23 class thread
     24 {
     25 public:
     26     class id;
     27     typedef pthread_t native_handle_type;
     28 
     29     thread() noexcept;
     30     template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
     31     ~thread();
     32 
     33     thread(const thread&) = delete;
     34     thread(thread&& t) noexcept;
     35 
     36     thread& operator=(const thread&) = delete;
     37     thread& operator=(thread&& t) noexcept;
     38 
     39     void swap(thread& t) noexcept;
     40 
     41     bool joinable() const noexcept;
     42     void join();
     43     void detach();
     44     id get_id() const noexcept;
     45     native_handle_type native_handle();
     46 
     47     static unsigned hardware_concurrency() noexcept;
     48 };
     49 
     50 void swap(thread& x, thread& y) noexcept;
     51 
     52 class thread::id
     53 {
     54 public:
     55     id() noexcept;
     56 };
     57 
     58 bool operator==(thread::id x, thread::id y) noexcept;
     59 bool operator!=(thread::id x, thread::id y) noexcept;
     60 bool operator< (thread::id x, thread::id y) noexcept;
     61 bool operator<=(thread::id x, thread::id y) noexcept;
     62 bool operator> (thread::id x, thread::id y) noexcept;
     63 bool operator>=(thread::id x, thread::id y) noexcept;
     64 
     65 template<class charT, class traits>
     66 basic_ostream<charT, traits>&
     67 operator<<(basic_ostream<charT, traits>& out, thread::id id);
     68 
     69 namespace this_thread
     70 {
     71 
     72 thread::id get_id() noexcept;
     73 
     74 void yield() noexcept;
     75 
     76 template <class Clock, class Duration>
     77 void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
     78 
     79 template <class Rep, class Period>
     80 void sleep_for(const chrono::duration<Rep, Period>& rel_time);
     81 
     82 }  // this_thread
     83 
     84 }  // std
     85 
     86 */
     87 
     88 #include <__config>
     89 #include <iosfwd>
     90 #include <__functional_base>
     91 #include <type_traits>
     92 #include <cstddef>
     93 #include <functional>
     94 #include <memory>
     95 #include <system_error>
     96 #include <chrono>
     97 #include <__mutex_base>
     98 #ifndef _LIBCPP_HAS_NO_VARIADICS
     99 #include <tuple>
    100 #endif
    101 #include <pthread.h>
    102 #include <sched.h>
    103 
    104 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    105 #pragma GCC system_header
    106 #endif
    107 
    108 #define __STDCPP_THREADS__ __cplusplus
    109 
    110 #ifdef _LIBCPP_HAS_NO_THREADS
    111 #error <thread> is not supported on this single threaded system
    112 #else // !_LIBCPP_HAS_NO_THREADS
    113 
    114 _LIBCPP_BEGIN_NAMESPACE_STD
    115 
    116 template <class _Tp>
    117 class __thread_specific_ptr
    118 {
    119     pthread_key_t __key_;
    120 
    121     __thread_specific_ptr(const __thread_specific_ptr&);
    122     __thread_specific_ptr& operator=(const __thread_specific_ptr&);
    123 
    124     static void __at_thread_exit(void*);
    125 public:
    126     typedef _Tp* pointer;
    127 
    128     __thread_specific_ptr();
    129     ~__thread_specific_ptr();
    130 
    131     _LIBCPP_INLINE_VISIBILITY
    132     pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));}
    133     _LIBCPP_INLINE_VISIBILITY
    134     pointer operator*() const {return *get();}
    135     _LIBCPP_INLINE_VISIBILITY
    136     pointer operator->() const {return get();}
    137     pointer release();
    138     void reset(pointer __p = nullptr);
    139 };
    140 
    141 template <class _Tp>
    142 void
    143 __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
    144 {
    145     delete static_cast<pointer>(__p);
    146 }
    147 
    148 template <class _Tp>
    149 __thread_specific_ptr<_Tp>::__thread_specific_ptr()
    150 {
    151     int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
    152 #ifndef _LIBCPP_NO_EXCEPTIONS
    153     if (__ec)
    154         throw system_error(error_code(__ec, system_category()),
    155                            "__thread_specific_ptr construction failed");
    156 #endif
    157 }
    158 
    159 template <class _Tp>
    160 __thread_specific_ptr<_Tp>::~__thread_specific_ptr()
    161 {
    162     pthread_key_delete(__key_);
    163 }
    164 
    165 template <class _Tp>
    166 typename __thread_specific_ptr<_Tp>::pointer
    167 __thread_specific_ptr<_Tp>::release()
    168 {
    169     pointer __p = get();
    170     pthread_setspecific(__key_, 0);
    171     return __p;
    172 }
    173 
    174 template <class _Tp>
    175 void
    176 __thread_specific_ptr<_Tp>::reset(pointer __p)
    177 {
    178     pointer __p_old = get();
    179     pthread_setspecific(__key_, __p);
    180     delete __p_old;
    181 }
    182 
    183 class _LIBCPP_TYPE_VIS thread;
    184 class _LIBCPP_TYPE_VIS __thread_id;
    185 
    186 namespace this_thread
    187 {
    188 
    189 _LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
    190 
    191 }  // this_thread
    192 
    193 template<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
    194 
    195 class _LIBCPP_TYPE_VIS_ONLY __thread_id
    196 {
    197     // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
    198     // NULL is the no-thread value on Darwin.  Someone needs to check
    199     // on other platforms.  We assume 0 works everywhere for now.
    200     pthread_t __id_;
    201 
    202 public:
    203     _LIBCPP_INLINE_VISIBILITY
    204     __thread_id() _NOEXCEPT : __id_(0) {}
    205 
    206     friend _LIBCPP_INLINE_VISIBILITY
    207         bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
    208         {return __x.__id_ == __y.__id_;}
    209     friend _LIBCPP_INLINE_VISIBILITY
    210         bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
    211         {return !(__x == __y);}
    212     friend _LIBCPP_INLINE_VISIBILITY
    213         bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
    214         {return __x.__id_ < __y.__id_;}
    215     friend _LIBCPP_INLINE_VISIBILITY
    216         bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
    217         {return !(__y < __x);}
    218     friend _LIBCPP_INLINE_VISIBILITY
    219         bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
    220         {return   __y < __x ;}
    221     friend _LIBCPP_INLINE_VISIBILITY
    222         bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
    223         {return !(__x < __y);}
    224 
    225     template<class _CharT, class _Traits>
    226     friend
    227     _LIBCPP_INLINE_VISIBILITY
    228     basic_ostream<_CharT, _Traits>&
    229     operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
    230         {return __os << __id.__id_;}
    231 
    232 private:
    233     _LIBCPP_INLINE_VISIBILITY
    234     __thread_id(pthread_t __id) : __id_(__id) {}
    235 
    236     friend __thread_id this_thread::get_id() _NOEXCEPT;
    237     friend class _LIBCPP_TYPE_VIS thread;
    238     friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>;
    239 };
    240 
    241 template<>
    242 struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>
    243     : public unary_function<__thread_id, size_t>
    244 {
    245     _LIBCPP_INLINE_VISIBILITY
    246     size_t operator()(__thread_id __v) const
    247     {
    248         return hash<pthread_t>()(__v.__id_);
    249     }
    250 };
    251 
    252 namespace this_thread
    253 {
    254 
    255 inline _LIBCPP_INLINE_VISIBILITY
    256 __thread_id
    257 get_id() _NOEXCEPT
    258 {
    259     return pthread_self();
    260 }
    261 
    262 }  // this_thread
    263 
    264 class _LIBCPP_TYPE_VIS thread
    265 {
    266     pthread_t __t_;
    267 
    268     thread(const thread&);
    269     thread& operator=(const thread&);
    270 public:
    271     typedef __thread_id id;
    272     typedef pthread_t native_handle_type;
    273 
    274     _LIBCPP_INLINE_VISIBILITY
    275     thread() _NOEXCEPT : __t_(0) {}
    276 #ifndef _LIBCPP_HAS_NO_VARIADICS
    277     template <class _Fp, class ..._Args,
    278               class = typename enable_if
    279               <
    280                    !is_same<typename decay<_Fp>::type, thread>::value
    281               >::type
    282              >
    283         explicit thread(_Fp&& __f, _Args&&... __args);
    284 #else  // _LIBCPP_HAS_NO_VARIADICS
    285     template <class _Fp> explicit thread(_Fp __f);
    286 #endif
    287     ~thread();
    288 
    289 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    290     _LIBCPP_INLINE_VISIBILITY
    291     thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;}
    292     thread& operator=(thread&& __t) _NOEXCEPT;
    293 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    294 
    295     _LIBCPP_INLINE_VISIBILITY
    296     void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
    297 
    298     _LIBCPP_INLINE_VISIBILITY
    299     bool joinable() const _NOEXCEPT {return __t_ != 0;}
    300     void join();
    301     void detach();
    302     _LIBCPP_INLINE_VISIBILITY
    303     id get_id() const _NOEXCEPT {return __t_;}
    304     _LIBCPP_INLINE_VISIBILITY
    305     native_handle_type native_handle() _NOEXCEPT {return __t_;}
    306 
    307     static unsigned hardware_concurrency() _NOEXCEPT;
    308 };
    309 
    310 class __assoc_sub_state;
    311 
    312 class _LIBCPP_HIDDEN __thread_struct_imp;
    313 
    314 class _LIBCPP_TYPE_VIS __thread_struct
    315 {
    316     __thread_struct_imp* __p_;
    317 
    318     __thread_struct(const __thread_struct&);
    319     __thread_struct& operator=(const __thread_struct&);
    320 public:
    321     __thread_struct();
    322     ~__thread_struct();
    323 
    324     void notify_all_at_thread_exit(condition_variable*, mutex*);
    325     void __make_ready_at_thread_exit(__assoc_sub_state*);
    326 };
    327 
    328 _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
    329 
    330 #ifndef _LIBCPP_HAS_NO_VARIADICS
    331 
    332 template <class _Fp, class ..._Args, size_t ..._Indices>
    333 inline _LIBCPP_INLINE_VISIBILITY
    334 void
    335 __thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
    336 {
    337     __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
    338 }
    339 
    340 template <class _Fp>
    341 void*
    342 __thread_proxy(void* __vp)
    343 {
    344     __thread_local_data().reset(new __thread_struct);
    345     std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
    346     typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
    347     __thread_execute(*__p, _Index());
    348     return nullptr;
    349 }
    350 
    351 template <class _Fp, class ..._Args,
    352           class
    353          >
    354 thread::thread(_Fp&& __f, _Args&&... __args)
    355 {
    356     typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
    357     _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)),
    358                                 __decay_copy(_VSTD::forward<_Args>(__args))...));
    359     int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
    360     if (__ec == 0)
    361         __p.release();
    362     else
    363         __throw_system_error(__ec, "thread constructor failed");
    364 }
    365 
    366 #else  // _LIBCPP_HAS_NO_VARIADICS
    367 
    368 template <class _Fp>
    369 void*
    370 __thread_proxy(void* __vp)
    371 {
    372     __thread_local_data().reset(new __thread_struct);
    373     std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
    374     (*__p)();
    375     return nullptr;
    376 }
    377 
    378 template <class _Fp>
    379 thread::thread(_Fp __f)
    380 {
    381     std::unique_ptr<_Fp> __p(new _Fp(__f));
    382     int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get());
    383     if (__ec == 0)
    384         __p.release();
    385     else
    386         __throw_system_error(__ec, "thread constructor failed");
    387 }
    388 
    389 #endif  // _LIBCPP_HAS_NO_VARIADICS
    390 
    391 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    392 
    393 inline _LIBCPP_INLINE_VISIBILITY
    394 thread&
    395 thread::operator=(thread&& __t) _NOEXCEPT
    396 {
    397     if (__t_ != 0)
    398         terminate();
    399     __t_ = __t.__t_;
    400     __t.__t_ = 0;
    401     return *this;
    402 }
    403 
    404 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    405 
    406 inline _LIBCPP_INLINE_VISIBILITY
    407 void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
    408 
    409 namespace this_thread
    410 {
    411 
    412 _LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns);
    413 
    414 template <class _Rep, class _Period>
    415 void
    416 sleep_for(const chrono::duration<_Rep, _Period>& __d)
    417 {
    418     using namespace chrono;
    419     if (__d > duration<_Rep, _Period>::zero())
    420     {
    421         _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
    422         nanoseconds __ns;
    423         if (__d < _Max)
    424         {
    425             __ns = duration_cast<nanoseconds>(__d);
    426             if (__ns < __d)
    427                 ++__ns;
    428         }
    429         else
    430             __ns = nanoseconds::max();
    431         sleep_for(__ns);
    432     }
    433 }
    434 
    435 template <class _Clock, class _Duration>
    436 void
    437 sleep_until(const chrono::time_point<_Clock, _Duration>& __t)
    438 {
    439     using namespace chrono;
    440     mutex __mut;
    441     condition_variable __cv;
    442     unique_lock<mutex> __lk(__mut);
    443     while (_Clock::now() < __t)
    444         __cv.wait_until(__lk, __t);
    445 }
    446 
    447 template <class _Duration>
    448 inline _LIBCPP_INLINE_VISIBILITY
    449 void
    450 sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
    451 {
    452     using namespace chrono;
    453     sleep_for(__t - steady_clock::now());
    454 }
    455 
    456 inline _LIBCPP_INLINE_VISIBILITY
    457 void yield() _NOEXCEPT {sched_yield();}
    458 
    459 }  // this_thread
    460 
    461 _LIBCPP_END_NAMESPACE_STD
    462 
    463 #endif // !_LIBCPP_HAS_NO_THREADS
    464 
    465 #endif  // _LIBCPP_THREAD
    466