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