xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/std/thread (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj// <thread> -*- C++ -*-
238fd1498Szrj
338fd1498Szrj// Copyright (C) 2008-2018 Free Software Foundation, Inc.
438fd1498Szrj//
538fd1498Szrj// This file is part of the GNU ISO C++ Library.  This library is free
638fd1498Szrj// software; you can redistribute it and/or modify it under the
738fd1498Szrj// terms of the GNU General Public License as published by the
838fd1498Szrj// Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj// any later version.
1038fd1498Szrj
1138fd1498Szrj// This library is distributed in the hope that it will be useful,
1238fd1498Szrj// but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj// GNU General Public License for more details.
1538fd1498Szrj
1638fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj// permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj// 3.1, as published by the Free Software Foundation.
1938fd1498Szrj
2038fd1498Szrj// You should have received a copy of the GNU General Public License and
2138fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2338fd1498Szrj// <http://www.gnu.org/licenses/>.
2438fd1498Szrj
2538fd1498Szrj/** @file include/thread
2638fd1498Szrj *  This is a Standard C++ Library header.
2738fd1498Szrj */
2838fd1498Szrj
2938fd1498Szrj#ifndef _GLIBCXX_THREAD
3038fd1498Szrj#define _GLIBCXX_THREAD 1
3138fd1498Szrj
3238fd1498Szrj#pragma GCC system_header
3338fd1498Szrj
3438fd1498Szrj#if __cplusplus < 201103L
3538fd1498Szrj# include <bits/c++0x_warning.h>
3638fd1498Szrj#else
3738fd1498Szrj
3838fd1498Szrj#include <chrono>
3938fd1498Szrj#include <memory>
4038fd1498Szrj#include <tuple>
4138fd1498Szrj#include <cerrno>
4238fd1498Szrj#include <bits/functexcept.h>
4338fd1498Szrj#include <bits/functional_hash.h>
4438fd1498Szrj#include <bits/invoke.h>
4538fd1498Szrj#include <bits/gthr.h>
4638fd1498Szrj
4738fd1498Szrj#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
4838fd1498Szrj
4938fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default)
5038fd1498Szrj{
5138fd1498Szrj_GLIBCXX_BEGIN_NAMESPACE_VERSION
5238fd1498Szrj
5338fd1498Szrj  /**
5438fd1498Szrj   * @defgroup threads Threads
5538fd1498Szrj   * @ingroup concurrency
5638fd1498Szrj   *
5738fd1498Szrj   * Classes for thread support.
5838fd1498Szrj   * @{
5938fd1498Szrj   */
6038fd1498Szrj
6138fd1498Szrj  /// thread
6238fd1498Szrj  class thread
6338fd1498Szrj  {
6438fd1498Szrj  public:
6538fd1498Szrj    // Abstract base class for types that wrap arbitrary functors to be
6638fd1498Szrj    // invoked in the new thread of execution.
6738fd1498Szrj    struct _State
6838fd1498Szrj    {
6938fd1498Szrj      virtual ~_State();
7038fd1498Szrj      virtual void _M_run() = 0;
7138fd1498Szrj    };
7238fd1498Szrj    using _State_ptr = unique_ptr<_State>;
7338fd1498Szrj
7438fd1498Szrj    typedef __gthread_t			native_handle_type;
7538fd1498Szrj
7638fd1498Szrj    /// thread::id
7738fd1498Szrj    class id
7838fd1498Szrj    {
7938fd1498Szrj      native_handle_type	_M_thread;
8038fd1498Szrj
8138fd1498Szrj    public:
8238fd1498Szrj      id() noexcept : _M_thread() { }
8338fd1498Szrj
8438fd1498Szrj      explicit
8538fd1498Szrj      id(native_handle_type __id) : _M_thread(__id) { }
8638fd1498Szrj
8738fd1498Szrj    private:
8838fd1498Szrj      friend class thread;
8938fd1498Szrj      friend class hash<thread::id>;
9038fd1498Szrj
9138fd1498Szrj      friend bool
9238fd1498Szrj      operator==(thread::id __x, thread::id __y) noexcept;
9338fd1498Szrj
9438fd1498Szrj      friend bool
9538fd1498Szrj      operator<(thread::id __x, thread::id __y) noexcept;
9638fd1498Szrj
9738fd1498Szrj      template<class _CharT, class _Traits>
9838fd1498Szrj	friend basic_ostream<_CharT, _Traits>&
9938fd1498Szrj	operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id);
10038fd1498Szrj    };
10138fd1498Szrj
10238fd1498Szrj  private:
10338fd1498Szrj    id				_M_id;
10438fd1498Szrj
10538fd1498Szrj    // _GLIBCXX_RESOLVE_LIB_DEFECTS
10638fd1498Szrj    // 2097.  packaged_task constructors should be constrained
107*58e805e6Szrj    template<typename _Tp>
108*58e805e6Szrj      using __not_same = __not_<is_same<
109*58e805e6Szrj	typename remove_cv<typename remove_reference<_Tp>::type>::type,
110*58e805e6Szrj	thread>>;
11138fd1498Szrj
112*58e805e6Szrj  public:
113*58e805e6Szrj    thread() noexcept = default;
11438fd1498Szrj
115*58e805e6Szrj    template<typename _Callable, typename... _Args,
116*58e805e6Szrj	     typename = _Require<__not_same<_Callable>>>
11738fd1498Szrj      explicit
11838fd1498Szrj      thread(_Callable&& __f, _Args&&... __args)
11938fd1498Szrj      {
120*58e805e6Szrj	static_assert( __is_invocable<typename decay<_Callable>::type,
121*58e805e6Szrj				      typename decay<_Args>::type...>::value,
122*58e805e6Szrj	  "std::thread arguments must be invocable after conversion to rvalues"
123*58e805e6Szrj	  );
124*58e805e6Szrj
12538fd1498Szrj#ifdef GTHR_ACTIVE_PROXY
12638fd1498Szrj	// Create a reference to pthread_create, not just the gthr weak symbol.
12738fd1498Szrj	auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
12838fd1498Szrj#else
12938fd1498Szrj	auto __depend = nullptr;
13038fd1498Szrj#endif
13138fd1498Szrj        _M_start_thread(_S_make_state(
13238fd1498Szrj	      __make_invoker(std::forward<_Callable>(__f),
13338fd1498Szrj			     std::forward<_Args>(__args)...)),
13438fd1498Szrj	    __depend);
13538fd1498Szrj      }
13638fd1498Szrj
13738fd1498Szrj    ~thread()
13838fd1498Szrj    {
13938fd1498Szrj      if (joinable())
14038fd1498Szrj	std::terminate();
14138fd1498Szrj    }
14238fd1498Szrj
143*58e805e6Szrj    thread(const thread&) = delete;
144*58e805e6Szrj
145*58e805e6Szrj    thread(thread&& __t) noexcept
146*58e805e6Szrj    { swap(__t); }
147*58e805e6Szrj
14838fd1498Szrj    thread& operator=(const thread&) = delete;
14938fd1498Szrj
15038fd1498Szrj    thread& operator=(thread&& __t) noexcept
15138fd1498Szrj    {
15238fd1498Szrj      if (joinable())
15338fd1498Szrj	std::terminate();
15438fd1498Szrj      swap(__t);
15538fd1498Szrj      return *this;
15638fd1498Szrj    }
15738fd1498Szrj
15838fd1498Szrj    void
15938fd1498Szrj    swap(thread& __t) noexcept
16038fd1498Szrj    { std::swap(_M_id, __t._M_id); }
16138fd1498Szrj
16238fd1498Szrj    bool
16338fd1498Szrj    joinable() const noexcept
16438fd1498Szrj    { return !(_M_id == id()); }
16538fd1498Szrj
16638fd1498Szrj    void
16738fd1498Szrj    join();
16838fd1498Szrj
16938fd1498Szrj    void
17038fd1498Szrj    detach();
17138fd1498Szrj
17238fd1498Szrj    thread::id
17338fd1498Szrj    get_id() const noexcept
17438fd1498Szrj    { return _M_id; }
17538fd1498Szrj
17638fd1498Szrj    /** @pre thread is joinable
17738fd1498Szrj     */
17838fd1498Szrj    native_handle_type
17938fd1498Szrj    native_handle()
18038fd1498Szrj    { return _M_id._M_thread; }
18138fd1498Szrj
18238fd1498Szrj    // Returns a value that hints at the number of hardware thread contexts.
18338fd1498Szrj    static unsigned int
18438fd1498Szrj    hardware_concurrency() noexcept;
18538fd1498Szrj
18638fd1498Szrj  private:
18738fd1498Szrj    template<typename _Callable>
18838fd1498Szrj      struct _State_impl : public _State
18938fd1498Szrj      {
19038fd1498Szrj	_Callable		_M_func;
19138fd1498Szrj
19238fd1498Szrj	_State_impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f))
19338fd1498Szrj	{ }
19438fd1498Szrj
19538fd1498Szrj	void
19638fd1498Szrj	_M_run() { _M_func(); }
19738fd1498Szrj      };
19838fd1498Szrj
19938fd1498Szrj    void
20038fd1498Szrj    _M_start_thread(_State_ptr, void (*)());
20138fd1498Szrj
20238fd1498Szrj    template<typename _Callable>
20338fd1498Szrj      static _State_ptr
20438fd1498Szrj      _S_make_state(_Callable&& __f)
20538fd1498Szrj      {
20638fd1498Szrj	using _Impl = _State_impl<_Callable>;
20738fd1498Szrj	return _State_ptr{new _Impl{std::forward<_Callable>(__f)}};
20838fd1498Szrj      }
20938fd1498Szrj#if _GLIBCXX_THREAD_ABI_COMPAT
21038fd1498Szrj  public:
21138fd1498Szrj    struct _Impl_base;
21238fd1498Szrj    typedef shared_ptr<_Impl_base>	__shared_base_type;
21338fd1498Szrj    struct _Impl_base
21438fd1498Szrj    {
21538fd1498Szrj      __shared_base_type	_M_this_ptr;
21638fd1498Szrj      virtual ~_Impl_base() = default;
21738fd1498Szrj      virtual void _M_run() = 0;
21838fd1498Szrj    };
21938fd1498Szrj
22038fd1498Szrj  private:
22138fd1498Szrj    void
22238fd1498Szrj    _M_start_thread(__shared_base_type, void (*)());
22338fd1498Szrj
22438fd1498Szrj    void
22538fd1498Szrj    _M_start_thread(__shared_base_type);
22638fd1498Szrj#endif
22738fd1498Szrj
22838fd1498Szrj  private:
22938fd1498Szrj    // A call wrapper that does INVOKE(forwarded tuple elements...)
23038fd1498Szrj    template<typename _Tuple>
23138fd1498Szrj      struct _Invoker
23238fd1498Szrj      {
23338fd1498Szrj	_Tuple _M_t;
23438fd1498Szrj
23538fd1498Szrj	template<size_t _Index>
23638fd1498Szrj	  static __tuple_element_t<_Index, _Tuple>&&
23738fd1498Szrj	  _S_declval();
23838fd1498Szrj
23938fd1498Szrj	template<size_t... _Ind>
24038fd1498Szrj	  auto
24138fd1498Szrj	  _M_invoke(_Index_tuple<_Ind...>)
24238fd1498Szrj	  noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
24338fd1498Szrj	  -> decltype(std::__invoke(_S_declval<_Ind>()...))
24438fd1498Szrj	  { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
24538fd1498Szrj
24638fd1498Szrj	using _Indices
24738fd1498Szrj	  = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
24838fd1498Szrj
24938fd1498Szrj	auto
25038fd1498Szrj	operator()()
25138fd1498Szrj	noexcept(noexcept(std::declval<_Invoker&>()._M_invoke(_Indices())))
25238fd1498Szrj	-> decltype(std::declval<_Invoker&>()._M_invoke(_Indices()))
25338fd1498Szrj	{ return _M_invoke(_Indices()); }
25438fd1498Szrj      };
25538fd1498Szrj
25638fd1498Szrj    template<typename... _Tp>
25738fd1498Szrj      using __decayed_tuple = tuple<typename std::decay<_Tp>::type...>;
25838fd1498Szrj
25938fd1498Szrj  public:
26038fd1498Szrj    // Returns a call wrapper that stores
26138fd1498Szrj    // tuple{DECAY_COPY(__callable), DECAY_COPY(__args)...}.
26238fd1498Szrj    template<typename _Callable, typename... _Args>
26338fd1498Szrj      static _Invoker<__decayed_tuple<_Callable, _Args...>>
26438fd1498Szrj      __make_invoker(_Callable&& __callable, _Args&&... __args)
26538fd1498Szrj      {
26638fd1498Szrj	return { __decayed_tuple<_Callable, _Args...>{
26738fd1498Szrj	    std::forward<_Callable>(__callable), std::forward<_Args>(__args)...
26838fd1498Szrj	} };
26938fd1498Szrj      }
27038fd1498Szrj  };
27138fd1498Szrj
27238fd1498Szrj  inline void
27338fd1498Szrj  swap(thread& __x, thread& __y) noexcept
27438fd1498Szrj  { __x.swap(__y); }
27538fd1498Szrj
27638fd1498Szrj  inline bool
27738fd1498Szrj  operator==(thread::id __x, thread::id __y) noexcept
27838fd1498Szrj  {
27938fd1498Szrj    // pthread_equal is undefined if either thread ID is not valid, so we
28038fd1498Szrj    // can't safely use __gthread_equal on default-constructed values (nor
28138fd1498Szrj    // the non-zero value returned by this_thread::get_id() for
28238fd1498Szrj    // single-threaded programs using GNU libc). Assume EqualityComparable.
28338fd1498Szrj    return __x._M_thread == __y._M_thread;
28438fd1498Szrj  }
28538fd1498Szrj
28638fd1498Szrj  inline bool
28738fd1498Szrj  operator!=(thread::id __x, thread::id __y) noexcept
28838fd1498Szrj  { return !(__x == __y); }
28938fd1498Szrj
29038fd1498Szrj  inline bool
29138fd1498Szrj  operator<(thread::id __x, thread::id __y) noexcept
29238fd1498Szrj  {
29338fd1498Szrj    // Pthreads doesn't define any way to do this, so we just have to
29438fd1498Szrj    // assume native_handle_type is LessThanComparable.
29538fd1498Szrj    return __x._M_thread < __y._M_thread;
29638fd1498Szrj  }
29738fd1498Szrj
29838fd1498Szrj  inline bool
29938fd1498Szrj  operator<=(thread::id __x, thread::id __y) noexcept
30038fd1498Szrj  { return !(__y < __x); }
30138fd1498Szrj
30238fd1498Szrj  inline bool
30338fd1498Szrj  operator>(thread::id __x, thread::id __y) noexcept
30438fd1498Szrj  { return __y < __x; }
30538fd1498Szrj
30638fd1498Szrj  inline bool
30738fd1498Szrj  operator>=(thread::id __x, thread::id __y) noexcept
30838fd1498Szrj  { return !(__x < __y); }
30938fd1498Szrj
31038fd1498Szrj  // DR 889.
31138fd1498Szrj  /// std::hash specialization for thread::id.
31238fd1498Szrj  template<>
31338fd1498Szrj    struct hash<thread::id>
31438fd1498Szrj    : public __hash_base<size_t, thread::id>
31538fd1498Szrj    {
31638fd1498Szrj      size_t
31738fd1498Szrj      operator()(const thread::id& __id) const noexcept
31838fd1498Szrj      { return std::_Hash_impl::hash(__id._M_thread); }
31938fd1498Szrj    };
32038fd1498Szrj
32138fd1498Szrj  template<class _CharT, class _Traits>
32238fd1498Szrj    inline basic_ostream<_CharT, _Traits>&
32338fd1498Szrj    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
32438fd1498Szrj    {
32538fd1498Szrj      if (__id == thread::id())
32638fd1498Szrj	return __out << "thread::id of a non-executing thread";
32738fd1498Szrj      else
32838fd1498Szrj	return __out << __id._M_thread;
32938fd1498Szrj    }
33038fd1498Szrj
33138fd1498Szrj  /** @namespace std::this_thread
33238fd1498Szrj   *  @brief ISO C++ 2011 entities sub-namespace for thread.
33338fd1498Szrj   *  30.3.2 Namespace this_thread.
33438fd1498Szrj   */
33538fd1498Szrj  namespace this_thread
33638fd1498Szrj  {
33738fd1498Szrj    /// get_id
33838fd1498Szrj    inline thread::id
33938fd1498Szrj    get_id() noexcept
34038fd1498Szrj    {
34138fd1498Szrj#ifdef __GLIBC__
34238fd1498Szrj      // For the GNU C library pthread_self() is usable without linking to
34338fd1498Szrj      // libpthread.so but returns 0, so we cannot use it in single-threaded
34438fd1498Szrj      // programs, because this_thread::get_id() != thread::id{} must be true.
34538fd1498Szrj      // We know that pthread_t is an integral type in the GNU C library.
34638fd1498Szrj      if (!__gthread_active_p())
34738fd1498Szrj	return thread::id(1);
34838fd1498Szrj#endif
34938fd1498Szrj      return thread::id(__gthread_self());
35038fd1498Szrj    }
35138fd1498Szrj
35238fd1498Szrj    /// yield
35338fd1498Szrj    inline void
35438fd1498Szrj    yield() noexcept
35538fd1498Szrj    {
35638fd1498Szrj#ifdef _GLIBCXX_USE_SCHED_YIELD
35738fd1498Szrj      __gthread_yield();
35838fd1498Szrj#endif
35938fd1498Szrj    }
36038fd1498Szrj
36138fd1498Szrj    void
36238fd1498Szrj    __sleep_for(chrono::seconds, chrono::nanoseconds);
36338fd1498Szrj
36438fd1498Szrj    /// sleep_for
36538fd1498Szrj    template<typename _Rep, typename _Period>
36638fd1498Szrj      inline void
36738fd1498Szrj      sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
36838fd1498Szrj      {
36938fd1498Szrj	if (__rtime <= __rtime.zero())
37038fd1498Szrj	  return;
37138fd1498Szrj	auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
37238fd1498Szrj	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
37338fd1498Szrj#ifdef _GLIBCXX_USE_NANOSLEEP
37438fd1498Szrj	__gthread_time_t __ts =
37538fd1498Szrj	  {
37638fd1498Szrj	    static_cast<std::time_t>(__s.count()),
37738fd1498Szrj	    static_cast<long>(__ns.count())
37838fd1498Szrj	  };
37938fd1498Szrj	while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
38038fd1498Szrj	  { }
38138fd1498Szrj#else
38238fd1498Szrj	__sleep_for(__s, __ns);
38338fd1498Szrj#endif
38438fd1498Szrj      }
38538fd1498Szrj
38638fd1498Szrj    /// sleep_until
38738fd1498Szrj    template<typename _Clock, typename _Duration>
38838fd1498Szrj      inline void
38938fd1498Szrj      sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
39038fd1498Szrj      {
39138fd1498Szrj	auto __now = _Clock::now();
39238fd1498Szrj	if (_Clock::is_steady)
39338fd1498Szrj	  {
39438fd1498Szrj	    if (__now < __atime)
39538fd1498Szrj	      sleep_for(__atime - __now);
39638fd1498Szrj	    return;
39738fd1498Szrj	  }
39838fd1498Szrj	while (__now < __atime)
39938fd1498Szrj	  {
40038fd1498Szrj	    sleep_for(__atime - __now);
40138fd1498Szrj	    __now = _Clock::now();
40238fd1498Szrj	  }
40338fd1498Szrj      }
40438fd1498Szrj  }
40538fd1498Szrj
40638fd1498Szrj  // @} group threads
40738fd1498Szrj
40838fd1498Szrj_GLIBCXX_END_NAMESPACE_VERSION
40938fd1498Szrj} // namespace
41038fd1498Szrj
41138fd1498Szrj#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
41238fd1498Szrj
41338fd1498Szrj#endif // C++11
41438fd1498Szrj
41538fd1498Szrj#endif // _GLIBCXX_THREAD
416