]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/libc++/src/thread.cpp
Merged libcxxrt and libc++. Now available for testing on 9-stable with
[FreeBSD/stable/9.git] / contrib / libc++ / src / thread.cpp
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 && !__sun__
16 #include <sys/sysctl.h>
17 #endif // _WIN32
18
19 _LIBCPP_BEGIN_NAMESPACE_STD
20
21 thread::~thread()
22 {
23     if (__t_ != 0)
24         terminate();
25 }
26
27 void
28 thread::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
38 void
39 thread::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
54 unsigned
55 thread::hardware_concurrency()
56 {
57 #if defined(CTL_HW) && defined(HW_NCPU)
58     unsigned 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
70 namespace this_thread
71 {
72
73 void
74 sleep_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
97 template <class T>
98 class _LIBCPP_HIDDEN __hidden_allocator
99 {
100 public:
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
110 class _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&);
122 public:
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
146 void
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
152 void
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
171 void
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
177 void
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