thread.cpp revision 227825
1227825Stheraven//===------------------------- thread.cpp----------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "thread" 11227825Stheraven#include "exception" 12227825Stheraven#include "vector" 13227825Stheraven#include "future" 14227825Stheraven#include <sys/types.h> 15227825Stheraven#if !_WIN32 16227825Stheraven#include <sys/sysctl.h> 17227825Stheraven#endif // _WIN32 18227825Stheraven 19227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 20227825Stheraven 21227825Stheraventhread::~thread() 22227825Stheraven{ 23227825Stheraven if (__t_ != 0) 24227825Stheraven terminate(); 25227825Stheraven} 26227825Stheraven 27227825Stheravenvoid 28227825Stheraventhread::join() 29227825Stheraven{ 30227825Stheraven int ec = pthread_join(__t_, 0); 31227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 32227825Stheraven if (ec) 33227825Stheraven throw system_error(error_code(ec, system_category()), "thread::join failed"); 34227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 35227825Stheraven __t_ = 0; 36227825Stheraven} 37227825Stheraven 38227825Stheravenvoid 39227825Stheraventhread::detach() 40227825Stheraven{ 41227825Stheraven int ec = EINVAL; 42227825Stheraven if (__t_ != 0) 43227825Stheraven { 44227825Stheraven ec = pthread_detach(__t_); 45227825Stheraven if (ec == 0) 46227825Stheraven __t_ = 0; 47227825Stheraven } 48227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 49227825Stheraven if (ec) 50227825Stheraven throw system_error(error_code(ec, system_category()), "thread::detach failed"); 51227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 52227825Stheraven} 53227825Stheraven 54227825Stheravenunsigned 55227825Stheraventhread::hardware_concurrency() 56227825Stheraven{ 57227825Stheraven#if defined(CTL_HW) && defined(HW_NCPU) 58227825Stheraven int n; 59227825Stheraven int mib[2] = {CTL_HW, HW_NCPU}; 60227825Stheraven std::size_t s = sizeof(n); 61227825Stheraven sysctl(mib, 2, &n, &s, 0, 0); 62227825Stheraven return n; 63227825Stheraven#else // defined(CTL_HW) && defined(HW_NCPU) 64227825Stheraven // TODO: grovel through /proc or check cpuid on x86 and similar 65227825Stheraven // instructions on other architectures. 66227825Stheraven return 0; // Means not computable [thread.thread.static] 67227825Stheraven#endif // defined(CTL_HW) && defined(HW_NCPU) 68227825Stheraven} 69227825Stheraven 70227825Stheravennamespace this_thread 71227825Stheraven{ 72227825Stheraven 73227825Stheravenvoid 74227825Stheravensleep_for(const chrono::nanoseconds& ns) 75227825Stheraven{ 76227825Stheraven using namespace chrono; 77227825Stheraven if (ns >= nanoseconds::zero()) 78227825Stheraven { 79227825Stheraven timespec ts; 80227825Stheraven ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count()); 81227825Stheraven ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count()); 82227825Stheraven nanosleep(&ts, 0); 83227825Stheraven } 84227825Stheraven} 85227825Stheraven 86227825Stheraven} // this_thread 87227825Stheraven 88227825Stheraven__thread_specific_ptr<__thread_struct>& 89227825Stheraven__thread_local_data() 90227825Stheraven{ 91227825Stheraven static __thread_specific_ptr<__thread_struct> __p; 92227825Stheraven return __p; 93227825Stheraven} 94227825Stheraven 95227825Stheraven// __thread_struct_imp 96227825Stheraven 97227825Stheraventemplate <class T> 98227825Stheravenclass _LIBCPP_HIDDEN __hidden_allocator 99227825Stheraven{ 100227825Stheravenpublic: 101227825Stheraven typedef T value_type; 102227825Stheraven 103227825Stheraven T* allocate(size_t __n) 104227825Stheraven {return static_cast<T*>(::operator new(__n * sizeof(T)));} 105227825Stheraven void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 106227825Stheraven 107227825Stheraven size_t max_size() const {return size_t(~0) / sizeof(T);} 108227825Stheraven}; 109227825Stheraven 110227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp 111227825Stheraven{ 112227825Stheraven typedef vector<__assoc_sub_state*, 113227825Stheraven __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 114227825Stheraven typedef vector<pair<condition_variable*, mutex*>, 115227825Stheraven __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 116227825Stheraven 117227825Stheraven _AsyncStates async_states_; 118227825Stheraven _Notify notify_; 119227825Stheraven 120227825Stheraven __thread_struct_imp(const __thread_struct_imp&); 121227825Stheraven __thread_struct_imp& operator=(const __thread_struct_imp&); 122227825Stheravenpublic: 123227825Stheraven __thread_struct_imp() {} 124227825Stheraven ~__thread_struct_imp(); 125227825Stheraven 126227825Stheraven void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 127227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state* __s); 128227825Stheraven}; 129227825Stheraven 130227825Stheraven__thread_struct_imp::~__thread_struct_imp() 131227825Stheraven{ 132227825Stheraven for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 133227825Stheraven i != e; ++i) 134227825Stheraven { 135227825Stheraven i->second->unlock(); 136227825Stheraven i->first->notify_all(); 137227825Stheraven } 138227825Stheraven for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 139227825Stheraven i != e; ++i) 140227825Stheraven { 141227825Stheraven (*i)->__make_ready(); 142227825Stheraven (*i)->__release_shared(); 143227825Stheraven } 144227825Stheraven} 145227825Stheraven 146227825Stheravenvoid 147227825Stheraven__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 148227825Stheraven{ 149227825Stheraven notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 150227825Stheraven} 151227825Stheraven 152227825Stheravenvoid 153227825Stheraven__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 154227825Stheraven{ 155227825Stheraven async_states_.push_back(__s); 156227825Stheraven __s->__add_shared(); 157227825Stheraven} 158227825Stheraven 159227825Stheraven// __thread_struct 160227825Stheraven 161227825Stheraven__thread_struct::__thread_struct() 162227825Stheraven : __p_(new __thread_struct_imp) 163227825Stheraven{ 164227825Stheraven} 165227825Stheraven 166227825Stheraven__thread_struct::~__thread_struct() 167227825Stheraven{ 168227825Stheraven delete __p_; 169227825Stheraven} 170227825Stheraven 171227825Stheravenvoid 172227825Stheraven__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 173227825Stheraven{ 174227825Stheraven __p_->notify_all_at_thread_exit(cv, m); 175227825Stheraven} 176227825Stheraven 177227825Stheravenvoid 178227825Stheraven__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 179227825Stheraven{ 180227825Stheraven __p_->__make_ready_at_thread_exit(__s); 181227825Stheraven} 182227825Stheraven 183227825Stheraven_LIBCPP_END_NAMESPACE_STD 184