thread.cpp revision 227825
1//===------------------------- thread.cpp----------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "thread" 11#include "exception" 12#include "vector" 13#include "future" 14#include <sys/types.h> 15#if !_WIN32 16#include <sys/sysctl.h> 17#endif // _WIN32 18 19_LIBCPP_BEGIN_NAMESPACE_STD 20 21thread::~thread() 22{ 23 if (__t_ != 0) 24 terminate(); 25} 26 27void 28thread::join() 29{ 30 int ec = pthread_join(__t_, 0); 31#ifndef _LIBCPP_NO_EXCEPTIONS 32 if (ec) 33 throw system_error(error_code(ec, system_category()), "thread::join failed"); 34#endif // _LIBCPP_NO_EXCEPTIONS 35 __t_ = 0; 36} 37 38void 39thread::detach() 40{ 41 int ec = EINVAL; 42 if (__t_ != 0) 43 { 44 ec = pthread_detach(__t_); 45 if (ec == 0) 46 __t_ = 0; 47 } 48#ifndef _LIBCPP_NO_EXCEPTIONS 49 if (ec) 50 throw system_error(error_code(ec, system_category()), "thread::detach failed"); 51#endif // _LIBCPP_NO_EXCEPTIONS 52} 53 54unsigned 55thread::hardware_concurrency() 56{ 57#if defined(CTL_HW) && defined(HW_NCPU) 58 int n; 59 int mib[2] = {CTL_HW, HW_NCPU}; 60 std::size_t s = sizeof(n); 61 sysctl(mib, 2, &n, &s, 0, 0); 62 return n; 63#else // defined(CTL_HW) && defined(HW_NCPU) 64 // TODO: grovel through /proc or check cpuid on x86 and similar 65 // instructions on other architectures. 66 return 0; // Means not computable [thread.thread.static] 67#endif // defined(CTL_HW) && defined(HW_NCPU) 68} 69 70namespace this_thread 71{ 72 73void 74sleep_for(const chrono::nanoseconds& ns) 75{ 76 using namespace chrono; 77 if (ns >= nanoseconds::zero()) 78 { 79 timespec ts; 80 ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count()); 81 ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count()); 82 nanosleep(&ts, 0); 83 } 84} 85 86} // this_thread 87 88__thread_specific_ptr<__thread_struct>& 89__thread_local_data() 90{ 91 static __thread_specific_ptr<__thread_struct> __p; 92 return __p; 93} 94 95// __thread_struct_imp 96 97template <class T> 98class _LIBCPP_HIDDEN __hidden_allocator 99{ 100public: 101 typedef T value_type; 102 103 T* allocate(size_t __n) 104 {return static_cast<T*>(::operator new(__n * sizeof(T)));} 105 void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 106 107 size_t max_size() const {return size_t(~0) / sizeof(T);} 108}; 109 110class _LIBCPP_HIDDEN __thread_struct_imp 111{ 112 typedef vector<__assoc_sub_state*, 113 __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 114 typedef vector<pair<condition_variable*, mutex*>, 115 __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 116 117 _AsyncStates async_states_; 118 _Notify notify_; 119 120 __thread_struct_imp(const __thread_struct_imp&); 121 __thread_struct_imp& operator=(const __thread_struct_imp&); 122public: 123 __thread_struct_imp() {} 124 ~__thread_struct_imp(); 125 126 void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 127 void __make_ready_at_thread_exit(__assoc_sub_state* __s); 128}; 129 130__thread_struct_imp::~__thread_struct_imp() 131{ 132 for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 133 i != e; ++i) 134 { 135 i->second->unlock(); 136 i->first->notify_all(); 137 } 138 for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 139 i != e; ++i) 140 { 141 (*i)->__make_ready(); 142 (*i)->__release_shared(); 143 } 144} 145 146void 147__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 148{ 149 notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 150} 151 152void 153__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 154{ 155 async_states_.push_back(__s); 156 __s->__add_shared(); 157} 158 159// __thread_struct 160 161__thread_struct::__thread_struct() 162 : __p_(new __thread_struct_imp) 163{ 164} 165 166__thread_struct::~__thread_struct() 167{ 168 delete __p_; 169} 170 171void 172__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 173{ 174 __p_->notify_all_at_thread_exit(cv, m); 175} 176 177void 178__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 179{ 180 __p_->__make_ready_at_thread_exit(__s); 181} 182 183_LIBCPP_END_NAMESPACE_STD 184