thread.cpp revision 253159
118316Swollman//===------------------------- thread.cpp----------------------------------===// 218316Swollman// 318316Swollman// The LLVM Compiler Infrastructure 418316Swollman// 518316Swollman// This file is dual licensed under the MIT and the University of Illinois Open 618316Swollman// Source Licenses. See LICENSE.TXT for details. 718316Swollman// 818316Swollman//===----------------------------------------------------------------------===// 918316Swollman 1018316Swollman#include "thread" 1118316Swollman#include "exception" 1218316Swollman#include "vector" 1318316Swollman#include "future" 1418316Swollman#include "limits" 1518316Swollman#include <sys/types.h> 1618316Swollman#if !defined(_WIN32) 1718316Swollman#if !defined(__sun__) && !defined(__linux__) 1818316Swollman#include <sys/sysctl.h> 1918316Swollman#endif // !__sun__ && !__linux__ 2018316Swollman#include <unistd.h> 2118316Swollman#endif // !_WIN32 2218316Swollman 2318316Swollman#if defined(__NetBSD__) 2418316Swollman#pragma weak pthread_create // Do not create libpthread dependency 2518316Swollman#endif 2618316Swollman#if defined(_WIN32) 2718316Swollman#include <windows.h> 2846303Smarkm#endif 2950476Speter 3018316Swollman_LIBCPP_BEGIN_NAMESPACE_STD 3118316Swollman 3246303Smarkmthread::~thread() 3346303Smarkm{ 34126250Sbms if (__t_ != 0) 3546303Smarkm terminate(); 36126250Sbms} 37126250Sbms 38126250Sbmsvoid 39126250Sbmsthread::join() 40126250Sbms{ 4118316Swollman int ec = pthread_join(__t_, 0); 4218316Swollman#ifndef _LIBCPP_NO_EXCEPTIONS 4319880Swollman if (ec) 4419880Swollman throw system_error(error_code(ec, system_category()), "thread::join failed"); 4546303Smarkm#else 4619880Swollman (void)ec; 4719880Swollman#endif // _LIBCPP_NO_EXCEPTIONS 4818316Swollman __t_ = 0; 4918316Swollman} 5018316Swollman 5118316Swollmanvoid 5218316Swollmanthread::detach() 5318316Swollman{ 5419880Swollman int ec = EINVAL; 5518316Swollman if (__t_ != 0) 5618316Swollman { 5719880Swollman ec = pthread_detach(__t_); 58148726Sstefanf if (ec == 0) 59148726Sstefanf __t_ = 0; 6020339Swollman } 6120339Swollman#ifndef _LIBCPP_NO_EXCEPTIONS 6219880Swollman if (ec) 6319880Swollman throw system_error(error_code(ec, system_category()), "thread::detach failed"); 6419880Swollman#endif // _LIBCPP_NO_EXCEPTIONS 6519880Swollman} 6620339Swollman 6720339Swollmanunsigned 6820339Swollmanthread::hardware_concurrency() _NOEXCEPT 6920339Swollman{ 7020339Swollman#if defined(CTL_HW) && defined(HW_NCPU) 7118316Swollman unsigned n; 7218316Swollman int mib[2] = {CTL_HW, HW_NCPU}; 7318316Swollman std::size_t s = sizeof(n); 7418316Swollman sysctl(mib, 2, &n, &s, 0, 0); 7518316Swollman return n; 7618316Swollman#elif defined(_SC_NPROCESSORS_ONLN) 7718316Swollman long result = sysconf(_SC_NPROCESSORS_ONLN); 7818316Swollman // sysconf returns -1 if the name is invalid, the option does not exist or 7918316Swollman // does not have a definite limit. 8018316Swollman // if sysconf returns some other negative number, we have no idea 8118316Swollman // what is going on. Default to something safe. 8218316Swollman if (result < 0) 8318316Swollman return 0; 84148726Sstefanf return static_cast<unsigned>(result); 8518316Swollman#elif defined(_WIN32) 8619880Swollman SYSTEM_INFO info; 8719880Swollman GetSystemInfo(&info); 8819880Swollman return info.dwNumberOfProcessors; 8919880Swollman#else // defined(CTL_HW) && defined(HW_NCPU) 9019880Swollman // TODO: grovel through /proc or check cpuid on x86 and similar 9119880Swollman // instructions on other architectures. 9219880Swollman#warning hardware_concurrency not yet implemented 9319880Swollman return 0; // Means not computable [thread.thread.static] 9419880Swollman#endif // defined(CTL_HW) && defined(HW_NCPU) 9519880Swollman} 9619880Swollman 9719880Swollmannamespace this_thread 9819880Swollman{ 99190713Sphk 10019880Swollmanvoid 10119880Swollmansleep_for(const chrono::nanoseconds& ns) 10219880Swollman{ 10319880Swollman using namespace chrono; 10419880Swollman if (ns > nanoseconds::zero()) 10519880Swollman { 10620606Swollman seconds s = duration_cast<seconds>(ns); 10720606Swollman timespec ts; 10820606Swollman typedef decltype(ts.tv_sec) ts_sec; 10920606Swollman _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 11020606Swollman if (s.count() < ts_sec_max) 11120606Swollman { 11220606Swollman ts.tv_sec = static_cast<ts_sec>(s.count()); 11320606Swollman ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); 11420606Swollman } 11520606Swollman else 11620606Swollman { 11720606Swollman ts.tv_sec = ts_sec_max; 11820606Swollman ts.tv_nsec = giga::num - 1; 11919880Swollman } 12019880Swollman nanosleep(&ts, 0); 12119880Swollman } 12219880Swollman} 12319880Swollman 12419880Swollman} // this_thread 12519880Swollman 12619880Swollman__thread_specific_ptr<__thread_struct>& 12719880Swollman__thread_local_data() 12818316Swollman{ 12918316Swollman static __thread_specific_ptr<__thread_struct> __p; 13018316Swollman return __p; 13118316Swollman} 13218316Swollman 13318316Swollman// __thread_struct_imp 13418316Swollman 13518316Swollmantemplate <class T> 13619880Swollmanclass _LIBCPP_HIDDEN __hidden_allocator 13719880Swollman{ 13818316Swollmanpublic: 13919880Swollman typedef T value_type; 14018316Swollman 14118316Swollman T* allocate(size_t __n) 14219880Swollman {return static_cast<T*>(::operator new(__n * sizeof(T)));} 14346303Smarkm void deallocate(T* __p, size_t) {::operator delete((void*)__p);} 14418316Swollman 14518316Swollman size_t max_size() const {return size_t(~0) / sizeof(T);} 14646303Smarkm}; 14718316Swollman 14818316Swollmanclass _LIBCPP_HIDDEN __thread_struct_imp 14946303Smarkm{ 15020339Swollman typedef vector<__assoc_sub_state*, 15146303Smarkm __hidden_allocator<__assoc_sub_state*> > _AsyncStates; 15246303Smarkm typedef vector<pair<condition_variable*, mutex*>, 15346303Smarkm __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; 15418316Swollman 15519880Swollman _AsyncStates async_states_; 15619880Swollman _Notify notify_; 15719880Swollman 15819880Swollman __thread_struct_imp(const __thread_struct_imp&); 15919880Swollman __thread_struct_imp& operator=(const __thread_struct_imp&); 16018316Swollmanpublic: 16119880Swollman __thread_struct_imp() {} 16218316Swollman ~__thread_struct_imp(); 163286351Sdelphij 164286351Sdelphij void notify_all_at_thread_exit(condition_variable* cv, mutex* m); 165286351Sdelphij void __make_ready_at_thread_exit(__assoc_sub_state* __s); 166286351Sdelphij}; 167286351Sdelphij 168286351Sdelphij__thread_struct_imp::~__thread_struct_imp() 16918316Swollman{ 17019880Swollman for (_Notify::iterator i = notify_.begin(), e = notify_.end(); 17119880Swollman i != e; ++i) 17219880Swollman { 17318316Swollman i->second->unlock(); 17418316Swollman i->first->notify_all(); 17518316Swollman } 17618316Swollman for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); 17746303Smarkm i != e; ++i) 17819880Swollman { 17919880Swollman (*i)->__make_ready(); 18019880Swollman (*i)->__release_shared(); 18118316Swollman } 18218316Swollman} 18318316Swollman 18418316Swollmanvoid 18519880Swollman__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 18618316Swollman{ 18718316Swollman notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); 18818316Swollman} 18918316Swollman 19018316Swollmanvoid 19119880Swollman__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) 19218316Swollman{ 19337908Scharnier async_states_.push_back(__s); 19418316Swollman __s->__add_shared(); 19518316Swollman} 19618316Swollman 19718316Swollman// __thread_struct 19818316Swollman 19919880Swollman__thread_struct::__thread_struct() 20019880Swollman : __p_(new __thread_struct_imp) 20119880Swollman{ 20218316Swollman} 20318316Swollman 20418316Swollman__thread_struct::~__thread_struct() 20518316Swollman{ 20618316Swollman delete __p_; 20719880Swollman} 20818316Swollman 20919880Swollmanvoid 21019880Swollman__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) 21119880Swollman{ 21219880Swollman __p_->notify_all_at_thread_exit(cv, m); 21319880Swollman} 21419880Swollman 21519880Swollmanvoid 21619880Swollman__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) 21719880Swollman{ 21819880Swollman __p_->__make_ready_at_thread_exit(__s); 21919880Swollman} 22019880Swollman 22119880Swollman_LIBCPP_END_NAMESPACE_STD 22219880Swollman