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