]>
Commit | Line | Data |
---|---|---|
46e113bf CF |
1 | // <thread> -*- C++ -*- |
2 | ||
12ffa228 | 3 | // Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. |
46e113bf CF |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
46e113bf CF |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
46e113bf | 24 | |
f910786b | 25 | /** @file include/thread |
46e113bf CF |
26 | * This is a Standard C++ Library header. |
27 | */ | |
28 | ||
29 | #ifndef _GLIBCXX_THREAD | |
30 | #define _GLIBCXX_THREAD 1 | |
31 | ||
32 | #pragma GCC system_header | |
33 | ||
34 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ | |
ab65a4c7 | 35 | # include <bits/c++0x_warning.h> |
46e113bf CF |
36 | #else |
37 | ||
38 | #include <chrono> | |
46e113bf CF |
39 | #include <functional> |
40 | #include <memory> | |
41 | #include <mutex> | |
42 | #include <condition_variable> | |
46e113bf | 43 | #include <bits/functexcept.h> |
5c8db18a | 44 | #include <bits/functional_hash.h> |
46e113bf CF |
45 | #include <bits/gthr.h> |
46 | ||
47 | #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) | |
48 | ||
12ffa228 BK |
49 | namespace std _GLIBCXX_VISIBILITY(default) |
50 | { | |
51 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
53dc5044 | 52 | |
5b9daa7e BK |
53 | /** |
54 | * @defgroup threads Threads | |
55 | * @ingroup concurrency | |
56 | * | |
57 | * Classes for thread support. | |
58 | * @{ | |
59 | */ | |
60 | ||
d7afcd2b | 61 | /// thread |
8644ecf5 | 62 | class thread |
46e113bf CF |
63 | { |
64 | public: | |
626dda69 | 65 | typedef __gthread_t native_handle_type; |
f7459b6c BK |
66 | struct _Impl_base; |
67 | typedef shared_ptr<_Impl_base> __shared_base_type; | |
d7afcd2b BK |
68 | |
69 | /// thread::id | |
70 | class id | |
46e113bf | 71 | { |
626dda69 | 72 | native_handle_type _M_thread; |
d7afcd2b | 73 | |
46e113bf | 74 | public: |
7f0d79d5 | 75 | id() noexcept : _M_thread() { } |
d7afcd2b BK |
76 | |
77 | explicit | |
78 | id(native_handle_type __id) : _M_thread(__id) { } | |
79 | ||
80 | private: | |
81 | friend class thread; | |
5c8db18a | 82 | friend class hash<thread::id>; |
d7afcd2b BK |
83 | |
84 | friend bool | |
7f0d79d5 | 85 | operator==(thread::id __x, thread::id __y) noexcept |
d7afcd2b BK |
86 | { return __gthread_equal(__x._M_thread, __y._M_thread); } |
87 | ||
88 | friend bool | |
7f0d79d5 | 89 | operator<(thread::id __x, thread::id __y) noexcept |
d7afcd2b BK |
90 | { return __x._M_thread < __y._M_thread; } |
91 | ||
92 | template<class _CharT, class _Traits> | |
93 | friend basic_ostream<_CharT, _Traits>& | |
ff74fd13 | 94 | operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id); |
d7afcd2b BK |
95 | }; |
96 | ||
626dda69 | 97 | // Simple base type that the templatized, derived class containing |
9b3003d5 | 98 | // an arbitrary functor can be converted to and called. |
d7afcd2b BK |
99 | struct _Impl_base |
100 | { | |
626dda69 | 101 | __shared_base_type _M_this_ptr; |
d7afcd2b | 102 | |
d5545744 | 103 | inline virtual ~_Impl_base(); |
d7afcd2b | 104 | |
626dda69 | 105 | virtual void _M_run() = 0; |
46e113bf | 106 | }; |
46e113bf | 107 | |
d7afcd2b | 108 | template<typename _Callable> |
626dda69 | 109 | struct _Impl : public _Impl_base |
d7afcd2b | 110 | { |
626dda69 | 111 | _Callable _M_func; |
d7afcd2b | 112 | |
d7afcd2b BK |
113 | _Impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f)) |
114 | { } | |
115 | ||
626dda69 | 116 | void |
d7afcd2b BK |
117 | _M_run() { _M_func(); } |
118 | }; | |
119 | ||
120 | private: | |
626dda69 | 121 | id _M_id; |
d7afcd2b BK |
122 | |
123 | public: | |
7f0d79d5 | 124 | thread() noexcept = default; |
b2edc921 | 125 | thread(thread&) = delete; |
d7afcd2b BK |
126 | thread(const thread&) = delete; |
127 | ||
7f0d79d5 | 128 | thread(thread&& __t) noexcept |
d7afcd2b BK |
129 | { swap(__t); } |
130 | ||
46e113bf | 131 | template<typename _Callable, typename... _Args> |
1b3fad81 | 132 | explicit |
46e113bf | 133 | thread(_Callable&& __f, _Args&&... __args) |
1b3fad81 JW |
134 | { |
135 | _M_start_thread(_M_make_routine(std::bind<void>( | |
136 | std::forward<_Callable>(__f), | |
137 | std::forward<_Args>(__args)...))); | |
138 | } | |
46e113bf | 139 | |
959d14e1 | 140 | ~thread() |
cbdab9c8 JW |
141 | { |
142 | if (joinable()) | |
cd3b0faf | 143 | std::terminate(); |
cbdab9c8 | 144 | } |
46e113bf | 145 | |
46e113bf | 146 | thread& operator=(const thread&) = delete; |
d7afcd2b | 147 | |
7f0d79d5 | 148 | thread& operator=(thread&& __t) noexcept |
78b580a9 JW |
149 | { |
150 | if (joinable()) | |
cd3b0faf | 151 | std::terminate(); |
78b580a9 JW |
152 | swap(__t); |
153 | return *this; | |
154 | } | |
46e113bf | 155 | |
d7afcd2b | 156 | void |
7f0d79d5 | 157 | swap(thread& __t) noexcept |
626dda69 | 158 | { std::swap(_M_id, __t._M_id); } |
46e113bf | 159 | |
d7afcd2b | 160 | bool |
7f0d79d5 | 161 | joinable() const noexcept |
626dda69 | 162 | { return !(_M_id == id()); } |
46e113bf | 163 | |
d7afcd2b | 164 | void |
46e113bf CF |
165 | join(); |
166 | ||
d7afcd2b | 167 | void |
46e113bf CF |
168 | detach(); |
169 | ||
959d14e1 | 170 | thread::id |
7f0d79d5 | 171 | get_id() const noexcept |
626dda69 | 172 | { return _M_id; } |
46e113bf | 173 | |
cbdab9c8 JW |
174 | /** @pre thread is joinable |
175 | */ | |
d7afcd2b | 176 | native_handle_type |
46e113bf | 177 | native_handle() |
626dda69 | 178 | { return _M_id._M_thread; } |
46e113bf | 179 | |
d7afcd2b BK |
180 | // Returns a value that hints at the number of hardware thread contexts. |
181 | static unsigned int | |
7f0d79d5 | 182 | hardware_concurrency() noexcept |
d7afcd2b | 183 | { return 0; } |
46e113bf | 184 | |
46e113bf | 185 | private: |
626dda69 CF |
186 | void |
187 | _M_start_thread(__shared_base_type); | |
188 | ||
46e113bf | 189 | template<typename _Callable> |
d7afcd2b | 190 | shared_ptr<_Impl<_Callable>> |
626dda69 | 191 | _M_make_routine(_Callable&& __f) |
8644ecf5 | 192 | { |
d7afcd2b BK |
193 | // Create and allocate full data structure, not base. |
194 | return make_shared<_Impl<_Callable>>(std::forward<_Callable>(__f)); | |
46e113bf | 195 | } |
46e113bf CF |
196 | }; |
197 | ||
d5545744 BK |
198 | inline thread::_Impl_base::~_Impl_base() = default; |
199 | ||
46e113bf | 200 | inline void |
7f0d79d5 | 201 | swap(thread& __x, thread& __y) noexcept |
46e113bf CF |
202 | { __x.swap(__y); } |
203 | ||
d7afcd2b | 204 | inline bool |
7f0d79d5 | 205 | operator!=(thread::id __x, thread::id __y) noexcept |
d7afcd2b BK |
206 | { return !(__x == __y); } |
207 | ||
208 | inline bool | |
7f0d79d5 | 209 | operator<=(thread::id __x, thread::id __y) noexcept |
d7afcd2b BK |
210 | { return !(__y < __x); } |
211 | ||
212 | inline bool | |
7f0d79d5 | 213 | operator>(thread::id __x, thread::id __y) noexcept |
d7afcd2b BK |
214 | { return __y < __x; } |
215 | ||
216 | inline bool | |
7f0d79d5 | 217 | operator>=(thread::id __x, thread::id __y) noexcept |
d7afcd2b BK |
218 | { return !(__x < __y); } |
219 | ||
5c8db18a PC |
220 | // DR 889. |
221 | /// std::hash specialization for thread::id. | |
222 | template<> | |
223 | struct hash<thread::id> | |
5d64ee19 | 224 | : public __hash_base<size_t, thread::id> |
5c8db18a PC |
225 | { |
226 | size_t | |
227 | operator()(const thread::id& __id) const | |
e7f72940 | 228 | { return std::_Hash_impl::hash(__id._M_thread); } |
5c8db18a PC |
229 | }; |
230 | ||
d7afcd2b BK |
231 | template<class _CharT, class _Traits> |
232 | inline basic_ostream<_CharT, _Traits>& | |
ff74fd13 | 233 | operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id) |
d7afcd2b BK |
234 | { |
235 | if (__id == thread::id()) | |
236 | return __out << "thread::id of a non-executing thread"; | |
237 | else | |
238 | return __out << __id._M_thread; | |
239 | } | |
240 | ||
12ffa228 BK |
241 | _GLIBCXX_END_NAMESPACE_VERSION |
242 | ||
5b9daa7e BK |
243 | /** @namespace std::this_thread |
244 | * @brief ISO C++ 0x entities sub namespace for thread. | |
245 | * 30.2.2 Namespace this_thread. | |
246 | */ | |
46e113bf CF |
247 | namespace this_thread |
248 | { | |
12ffa228 BK |
249 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
250 | ||
f7459b6c | 251 | /// get_id |
4a50cd93 | 252 | inline thread::id |
7f0d79d5 | 253 | get_id() noexcept { return thread::id(__gthread_self()); } |
46e113bf | 254 | |
959d14e1 | 255 | #ifdef _GLIBCXX_USE_SCHED_YIELD |
f7459b6c | 256 | /// yield |
959d14e1 | 257 | inline void |
7f0d79d5 | 258 | yield() noexcept |
959d14e1 CF |
259 | { __gthread_yield(); } |
260 | #endif | |
46e113bf | 261 | |
959d14e1 | 262 | #ifdef _GLIBCXX_USE_NANOSLEEP |
f7459b6c | 263 | /// sleep_until |
46e113bf | 264 | template<typename _Clock, typename _Duration> |
959d14e1 | 265 | inline void |
46e113bf | 266 | sleep_until(const chrono::time_point<_Clock, _Duration>& __atime) |
959d14e1 | 267 | { sleep_for(__atime - _Clock::now()); } |
46e113bf | 268 | |
f7459b6c | 269 | /// sleep_for |
46e113bf | 270 | template<typename _Rep, typename _Period> |
959d14e1 | 271 | inline void |
46e113bf CF |
272 | sleep_for(const chrono::duration<_Rep, _Period>& __rtime) |
273 | { | |
274 | chrono::seconds __s = | |
275 | chrono::duration_cast<chrono::seconds>(__rtime); | |
276 | ||
277 | chrono::nanoseconds __ns = | |
278 | chrono::duration_cast<chrono::nanoseconds>(__rtime - __s); | |
279 | ||
d7afcd2b | 280 | __gthread_time_t __ts = |
46e113bf CF |
281 | { |
282 | static_cast<std::time_t>(__s.count()), | |
283 | static_cast<long>(__ns.count()) | |
284 | }; | |
285 | ||
46e113bf | 286 | ::nanosleep(&__ts, 0); |
46e113bf | 287 | } |
959d14e1 | 288 | #endif |
12ffa228 BK |
289 | |
290 | _GLIBCXX_END_NAMESPACE_VERSION | |
46e113bf | 291 | } |
5b9daa7e BK |
292 | |
293 | // @} group threads | |
12ffa228 BK |
294 | |
295 | } // namespace | |
46e113bf CF |
296 | |
297 | #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 | |
298 | ||
299 | #endif // __GXX_EXPERIMENTAL_CXX0X__ | |
300 | ||
301 | #endif // _GLIBCXX_THREAD |