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