1// -*- C++ -*- 2//===--------------------------- thread -----------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is distributed under the University of Illinois Open Source 7// License. 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 20namespace std 21{ 22 23class thread 24{ 25public: 26 class id; 27 typedef pthread_t native_handle_type; 28 29 thread(); 30 template <class F, class ...Args> explicit thread(F&& f, Args&&... args); 31 ~thread(); 32 33 thread(const thread&) = delete; 34 thread(thread&& t); 35 36 thread& operator=(const thread&) = delete; 37 thread& operator=(thread&& t); 38 39 void swap(thread& t); 40 41 bool joinable() const; 42 void join(); 43 void detach(); 44 id get_id() const; 45 native_handle_type native_handle(); 46 47 static unsigned hardware_concurrency(); 48}; 49 50void swap(thread& x, thread& y); 51 52class thread::id 53{ 54public: 55 id(); 56}; 57 58bool operator==(thread::id x, thread::id y); 59bool operator!=(thread::id x, thread::id y); 60bool operator< (thread::id x, thread::id y); 61bool operator<=(thread::id x, thread::id y); 62bool operator> (thread::id x, thread::id y); 63bool operator>=(thread::id x, thread::id y); 64 65template<class charT, class traits> 66basic_ostream<charT, traits>& 67operator<<(basic_ostream<charT, traits>& out, thread::id id); 68 69namespace this_thread 70{ 71 72thread::id get_id(); 73 74void yield(); 75 76template <class Clock, class Duration> 77void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); 78 79template <class Rep, class Period> 80void 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#include <pthread.h> 99 100#pragma GCC system_header 101 102#define __STDCPP_THREADS __cplusplus 103 104_LIBCPP_BEGIN_NAMESPACE_STD 105 106class thread; 107class __thread_id; 108 109namespace this_thread 110{ 111 112__thread_id get_id(); 113 114} // this_thread 115 116class __thread_id 117{ 118 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 119 // NULL is the no-thread value on Darwin. Someone needs to check 120 // on other platforms. We assume 0 works everywhere for now. 121 pthread_t __id_; 122 123public: 124 __thread_id() : __id_(0) {} 125 126 friend bool operator==(__thread_id __x, __thread_id __y) 127 {return __x.__id_ == __y.__id_;} 128 friend bool operator!=(__thread_id __x, __thread_id __y) 129 {return !(__x == __y);} 130 friend bool operator< (__thread_id __x, __thread_id __y) 131 {return __x.__id_ < __y.__id_;} 132 friend bool operator<=(__thread_id __x, __thread_id __y) 133 {return !(__y < __x);} 134 friend bool operator> (__thread_id __x, __thread_id __y) 135 {return __y < __x ;} 136 friend bool operator>=(__thread_id __x, __thread_id __y) 137 {return !(__x < __y);} 138 139 template<class _CharT, class _Traits> 140 friend 141 basic_ostream<_CharT, _Traits>& 142 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 143 {return __os << __id.__id_;} 144 145private: 146 __thread_id(pthread_t __id) : __id_(__id) {} 147 148 friend __thread_id this_thread::get_id(); 149 friend class thread; 150}; 151 152template<class _Tp> struct hash; 153 154template<> 155struct hash<__thread_id> 156 : public unary_function<__thread_id, size_t> 157{ 158 size_t operator()(__thread_id __v) const 159 { 160 const size_t* const __p = reinterpret_cast<const size_t*>(&__v); 161 return *__p; 162 } 163}; 164 165namespace this_thread 166{ 167 168inline 169__thread_id 170get_id() 171{ 172 return pthread_self(); 173} 174 175} // this_thread 176 177class thread 178{ 179 pthread_t __t_; 180 181#ifndef _LIBCPP_MOVE 182 thread(const thread&); // = delete; 183 thread& operator=(const thread&); // = delete; 184#endif 185public: 186 typedef __thread_id id; 187 typedef pthread_t native_handle_type; 188 189 thread() : __t_(0) {} 190#ifndef _LIBCPP_HAS_NO_VARIADICS 191 template <class _F, class ..._Args, 192 class = typename enable_if 193 < 194 !is_same<typename decay<_F>::type, thread>::value 195 >::type 196 > 197 explicit thread(_F&& __f, _Args&&... __args); 198#else 199 template <class _F> explicit thread(_F __f); 200#endif 201 ~thread(); 202 203#ifdef _LIBCPP_MOVE 204 thread(const thread&) = delete; 205 thread(thread&& __t) : __t_(__t.__t_) {__t.__t_ = 0;} 206 thread& operator=(const thread&) = delete; 207 thread& operator=(thread&& __t); 208#endif 209 210 void swap(thread& __t) {_STD::swap(__t_, __t.__t_);} 211 212 bool joinable() const {return __t_ != 0;} 213 void join(); 214 void detach(); 215 id get_id() const {return __t_;} 216 native_handle_type native_handle() {return __t_;} 217 218 static unsigned hardware_concurrency(); 219}; 220 221template <class _F> 222void* 223__thread_proxy(void* __vp) 224{ 225 std::unique_ptr<_F> __p(static_cast<_F*>(__vp)); 226 (*__p)(); 227 return nullptr; 228} 229 230#ifndef _LIBCPP_HAS_NO_VARIADICS 231 232template <class _F, class ..._Args, 233 class 234 > 235thread::thread(_F&& __f, _Args&&... __args) 236{ 237 typedef decltype(bind(std::forward<_F>(__f), std::forward<_Args>(__args)...)) _G; 238 std::unique_ptr<_G> __p(new _G(bind(std::forward<_F>(__f), 239 std::forward<_Args>(__args)...))); 240 int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get()); 241 if (__ec == 0) 242 __p.release(); 243 else 244 __throw_system_error(__ec, "thread constructor failed"); 245} 246 247#else 248 249template <class _F> 250thread::thread(_F __f) 251{ 252 std::unique_ptr<_F> __p(new _F(__f)); 253 int __ec = pthread_create(&__t_, 0, &__thread_proxy<_F>, __p.get()); 254 if (__ec == 0) 255 __p.release(); 256 else 257 __throw_system_error(__ec, "thread constructor failed"); 258} 259 260#endif 261 262#ifdef _LIBCPP_MOVE 263 264inline 265thread& 266thread::operator=(thread&& __t) 267{ 268 if (__t_ != 0) 269 terminate(); 270 __t_ = __t.__t_; 271 __t.__t_ = 0; 272 return *this; 273} 274 275#endif 276 277inline 278void swap(thread& __x, thread& __y) {__x.swap(__y);} 279 280 281namespace this_thread 282{ 283 284void sleep_for(const chrono::nanoseconds& ns); 285 286template <class _Rep, class _Period> 287void 288sleep_for(const chrono::duration<_Rep, _Period>& __d) 289{ 290 using namespace chrono; 291 nanoseconds __ns = duration_cast<nanoseconds>(__d); 292 if (__ns < __d) 293 ++__ns; 294 sleep_for(__ns); 295} 296 297template <class _Clock, class _Duration> 298void 299sleep_until(const chrono::time_point<_Clock, _Duration>& __t) 300{ 301 using namespace chrono; 302 mutex __mut; 303 condition_variable __cv; 304 unique_lock<mutex> __lk(__mut); 305 while (_Clock::now() < __t) 306 __cv.wait_until(__lk, __t); 307} 308 309template <class _Duration> 310inline 311void 312sleep_until(const chrono::time_point<chrono::monotonic_clock, _Duration>& __t) 313{ 314 using namespace chrono; 315 sleep_for(__t - monotonic_clock::now()); 316} 317 318inline 319void yield() {sched_yield();} 320 321} // this_thread 322 323_LIBCPP_END_NAMESPACE_STD 324 325#endif // _LIBCPP_THREAD 326