1// <thread> -*- C++ -*- 2 3// Copyright (C) 2008-2015 Free Software Foundation, Inc. 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 8// Free Software Foundation; either version 3, or (at your option) 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 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/>. 24 25/** @file include/thread 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#if __cplusplus < 201103L 35# include <bits/c++0x_warning.h> 36#else 37 38#include <chrono> 39#include <functional> 40#include <memory> 41#include <bits/functexcept.h> 42#include <bits/functional_hash.h> 43#include <bits/gthr.h> 44 45#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 46 47namespace std _GLIBCXX_VISIBILITY(default) 48{ 49_GLIBCXX_BEGIN_NAMESPACE_VERSION 50 51 /** 52 * @defgroup threads Threads 53 * @ingroup concurrency 54 * 55 * Classes for thread support. 56 * @{ 57 */ 58 59 /// thread 60 class thread 61 { 62 public: 63 typedef __gthread_t native_handle_type; 64 struct _Impl_base; 65 typedef shared_ptr<_Impl_base> __shared_base_type; 66 67 /// thread::id 68 class id 69 { 70 native_handle_type _M_thread; 71 72 public: 73 id() noexcept : _M_thread() { } 74 75 explicit 76 id(native_handle_type __id) : _M_thread(__id) { } 77 78 private: 79 friend class thread; 80 friend class hash<thread::id>; 81 82 friend bool 83 operator==(thread::id __x, thread::id __y) noexcept 84 { return __gthread_equal(__x._M_thread, __y._M_thread); } 85 86 friend bool 87 operator<(thread::id __x, thread::id __y) noexcept 88 { return __x._M_thread < __y._M_thread; } 89 90 template<class _CharT, class _Traits> 91 friend basic_ostream<_CharT, _Traits>& 92 operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id); 93 }; 94 95 // Simple base type that the templatized, derived class containing 96 // an arbitrary functor can be converted to and called. 97 struct _Impl_base 98 { 99 __shared_base_type _M_this_ptr; 100 101 inline virtual ~_Impl_base(); 102 103 virtual void _M_run() = 0; 104 }; 105 106 template<typename _Callable> 107 struct _Impl : public _Impl_base 108 { 109 _Callable _M_func; 110 111 _Impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f)) 112 { } 113 114 void 115 _M_run() { _M_func(); } 116 }; 117 118 private: 119 id _M_id; 120 121 public: 122 thread() noexcept = default; 123 // _GLIBCXX_RESOLVE_LIB_DEFECTS 124 // 2097. packaged_task constructors should be constrained 125 thread(thread&) = delete; 126 thread(const thread&) = delete; 127 128 thread(thread&& __t) noexcept 129 { swap(__t); } 130 131 template<typename _Callable, typename... _Args> 132 explicit 133 thread(_Callable&& __f, _Args&&... __args) 134 { 135#ifdef GTHR_ACTIVE_PROXY 136 // Create a reference to pthread_create, not just the gthr weak symbol 137 _M_start_thread(_M_make_routine(std::__bind_simple( 138 std::forward<_Callable>(__f), 139 std::forward<_Args>(__args)...)), 140 reinterpret_cast<void(*)()>(&pthread_create)); 141#else 142 _M_start_thread(_M_make_routine(std::__bind_simple( 143 std::forward<_Callable>(__f), 144 std::forward<_Args>(__args)...))); 145#endif 146 } 147 148 ~thread() 149 { 150 if (joinable()) 151 std::terminate(); 152 } 153 154 thread& operator=(const thread&) = delete; 155 156 thread& operator=(thread&& __t) noexcept 157 { 158 if (joinable()) 159 std::terminate(); 160 swap(__t); 161 return *this; 162 } 163 164 void 165 swap(thread& __t) noexcept 166 { std::swap(_M_id, __t._M_id); } 167 168 bool 169 joinable() const noexcept 170 { return !(_M_id == id()); } 171 172 void 173 join(); 174 175 void 176 detach(); 177 178 thread::id 179 get_id() const noexcept 180 { return _M_id; } 181 182 /** @pre thread is joinable 183 */ 184 native_handle_type 185 native_handle() 186 { return _M_id._M_thread; } 187 188 // Returns a value that hints at the number of hardware thread contexts. 189 static unsigned int 190 hardware_concurrency() noexcept; 191 192 private: 193 void 194 _M_start_thread(__shared_base_type, void (*)()); 195 196 void 197 _M_start_thread(__shared_base_type); 198 199 template<typename _Callable> 200 shared_ptr<_Impl<_Callable>> 201 _M_make_routine(_Callable&& __f) 202 { 203 // Create and allocate full data structure, not base. 204 return std::make_shared<_Impl<_Callable>>(std::forward<_Callable>(__f)); 205 } 206 }; 207 208 inline thread::_Impl_base::~_Impl_base() = default; 209 210 inline void 211 swap(thread& __x, thread& __y) noexcept 212 { __x.swap(__y); } 213 214 inline bool 215 operator!=(thread::id __x, thread::id __y) noexcept 216 { return !(__x == __y); } 217 218 inline bool 219 operator<=(thread::id __x, thread::id __y) noexcept 220 { return !(__y < __x); } 221 222 inline bool 223 operator>(thread::id __x, thread::id __y) noexcept 224 { return __y < __x; } 225 226 inline bool 227 operator>=(thread::id __x, thread::id __y) noexcept 228 { return !(__x < __y); } 229 230 // DR 889. 231 /// std::hash specialization for thread::id. 232 template<> 233 struct hash<thread::id> 234 : public __hash_base<size_t, thread::id> 235 { 236 size_t 237 operator()(const thread::id& __id) const noexcept 238 { return std::_Hash_impl::hash(__id._M_thread); } 239 }; 240 241 template<class _CharT, class _Traits> 242 inline basic_ostream<_CharT, _Traits>& 243 operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id) 244 { 245 if (__id == thread::id()) 246 return __out << "thread::id of a non-executing thread"; 247 else 248 return __out << __id._M_thread; 249 } 250 251_GLIBCXX_END_NAMESPACE_VERSION 252 253 /** @namespace std::this_thread 254 * @brief ISO C++ 2011 entities sub-namespace for thread. 255 * 30.3.2 Namespace this_thread. 256 */ 257 namespace this_thread 258 { 259 _GLIBCXX_BEGIN_NAMESPACE_VERSION 260 261 /// get_id 262 inline thread::id 263 get_id() noexcept { return thread::id(__gthread_self()); } 264 265 /// yield 266 inline void 267 yield() noexcept 268 { 269#ifdef _GLIBCXX_USE_SCHED_YIELD 270 __gthread_yield(); 271#endif 272 } 273 274 void 275 __sleep_for(chrono::seconds, chrono::nanoseconds); 276 277 /// sleep_for 278 template<typename _Rep, typename _Period> 279 inline void 280 sleep_for(const chrono::duration<_Rep, _Period>& __rtime) 281 { 282 if (__rtime <= __rtime.zero()) 283 return; 284 auto __s = chrono::duration_cast<chrono::seconds>(__rtime); 285 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s); 286#ifdef _GLIBCXX_USE_NANOSLEEP 287 __gthread_time_t __ts = 288 { 289 static_cast<std::time_t>(__s.count()), 290 static_cast<long>(__ns.count()) 291 }; 292 ::nanosleep(&__ts, 0); 293#else 294 __sleep_for(__s, __ns); 295#endif 296 } 297 298 /// sleep_until 299 template<typename _Clock, typename _Duration> 300 inline void 301 sleep_until(const chrono::time_point<_Clock, _Duration>& __atime) 302 { 303 auto __now = _Clock::now(); 304 if (__now < __atime) 305 sleep_for(__atime - __now); 306 } 307 308 _GLIBCXX_END_NAMESPACE_VERSION 309 } 310 311 // @} group threads 312 313} // namespace 314 315#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 316 317#endif // C++11 318 319#endif // _GLIBCXX_THREAD 320