123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- //===------------------------- thread.cpp----------------------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is dual licensed under the MIT and the University of Illinois Open
- // Source Licenses. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- #include "__config"
- #ifndef _LIBCPP_HAS_NO_THREADS
- #include "thread"
- #include "exception"
- #include "vector"
- #include "future"
- #include "limits"
- #include <sys/types.h>
- #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
- # include <sys/param.h>
- # if defined(BSD)
- # include <sys/sysctl.h>
- # endif // defined(BSD)
- #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
- #if !defined(_WIN32)
- # include <unistd.h>
- #endif // !_WIN32
- #if defined(__NetBSD__)
- #pragma weak pthread_create // Do not create libpthread dependency
- #endif
- #if defined(_WIN32)
- #include <windows.h>
- #endif
- _LIBCPP_BEGIN_NAMESPACE_STD
- thread::~thread()
- {
- if (__t_ != 0)
- terminate();
- }
- void
- thread::join()
- {
- int ec = EINVAL;
- if (__t_ != 0)
- {
- ec = __libcpp_thread_join(&__t_);
- if (ec == 0)
- __t_ = 0;
- }
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (ec)
- throw system_error(error_code(ec, system_category()), "thread::join failed");
- #endif // _LIBCPP_NO_EXCEPTIONS
- }
- void
- thread::detach()
- {
- int ec = EINVAL;
- if (__t_ != 0)
- {
- ec = __libcpp_thread_detach(&__t_);
- if (ec == 0)
- __t_ = 0;
- }
- #ifndef _LIBCPP_NO_EXCEPTIONS
- if (ec)
- throw system_error(error_code(ec, system_category()), "thread::detach failed");
- #endif // _LIBCPP_NO_EXCEPTIONS
- }
- unsigned
- thread::hardware_concurrency() _NOEXCEPT
- {
- #if defined(CTL_HW) && defined(HW_NCPU)
- unsigned n;
- int mib[2] = {CTL_HW, HW_NCPU};
- std::size_t s = sizeof(n);
- sysctl(mib, 2, &n, &s, 0, 0);
- return n;
- #elif defined(_SC_NPROCESSORS_ONLN)
- long result = sysconf(_SC_NPROCESSORS_ONLN);
- // sysconf returns -1 if the name is invalid, the option does not exist or
- // does not have a definite limit.
- // if sysconf returns some other negative number, we have no idea
- // what is going on. Default to something safe.
- if (result < 0)
- return 0;
- return static_cast<unsigned>(result);
- #elif defined(_WIN32)
- SYSTEM_INFO info;
- GetSystemInfo(&info);
- return info.dwNumberOfProcessors;
- #else // defined(CTL_HW) && defined(HW_NCPU)
- // TODO: grovel through /proc or check cpuid on x86 and similar
- // instructions on other architectures.
- # if defined(_MSC_VER) && ! defined(__clang__)
- _LIBCPP_WARNING("hardware_concurrency not yet implemented")
- # else
- # warning hardware_concurrency not yet implemented
- # endif
- return 0; // Means not computable [thread.thread.static]
- #endif // defined(CTL_HW) && defined(HW_NCPU)
- }
- namespace this_thread
- {
- void
- sleep_for(const chrono::nanoseconds& ns)
- {
- using namespace chrono;
- if (ns > nanoseconds::zero())
- {
- seconds s = duration_cast<seconds>(ns);
- timespec ts;
- typedef decltype(ts.tv_sec) ts_sec;
- _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
- if (s.count() < ts_sec_max)
- {
- ts.tv_sec = static_cast<ts_sec>(s.count());
- ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count());
- }
- else
- {
- ts.tv_sec = ts_sec_max;
- ts.tv_nsec = giga::num - 1;
- }
- while (nanosleep(&ts, &ts) == -1 && errno == EINTR)
- ;
- }
- }
- } // this_thread
- __thread_specific_ptr<__thread_struct>&
- __thread_local_data()
- {
- static __thread_specific_ptr<__thread_struct> __p;
- return __p;
- }
- // __thread_struct_imp
- template <class T>
- class _LIBCPP_HIDDEN __hidden_allocator
- {
- public:
- typedef T value_type;
-
- T* allocate(size_t __n)
- {return static_cast<T*>(::operator new(__n * sizeof(T)));}
- void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));}
- size_t max_size() const {return size_t(~0) / sizeof(T);}
- };
- class _LIBCPP_HIDDEN __thread_struct_imp
- {
- typedef vector<__assoc_sub_state*,
- __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
- typedef vector<pair<condition_variable*, mutex*>,
- __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
- _AsyncStates async_states_;
- _Notify notify_;
- __thread_struct_imp(const __thread_struct_imp&);
- __thread_struct_imp& operator=(const __thread_struct_imp&);
- public:
- __thread_struct_imp() {}
- ~__thread_struct_imp();
- void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
- void __make_ready_at_thread_exit(__assoc_sub_state* __s);
- };
- __thread_struct_imp::~__thread_struct_imp()
- {
- for (_Notify::iterator i = notify_.begin(), e = notify_.end();
- i != e; ++i)
- {
- i->second->unlock();
- i->first->notify_all();
- }
- for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
- i != e; ++i)
- {
- (*i)->__make_ready();
- (*i)->__release_shared();
- }
- }
- void
- __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
- {
- notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
- }
- void
- __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
- {
- async_states_.push_back(__s);
- __s->__add_shared();
- }
- // __thread_struct
- __thread_struct::__thread_struct()
- : __p_(new __thread_struct_imp)
- {
- }
- __thread_struct::~__thread_struct()
- {
- delete __p_;
- }
- void
- __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
- {
- __p_->notify_all_at_thread_exit(cv, m);
- }
- void
- __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
- {
- __p_->__make_ready_at_thread_exit(__s);
- }
- _LIBCPP_END_NAMESPACE_STD
- #endif // !_LIBCPP_HAS_NO_THREADS
|