// <thread> -*- C++ -*-

// Copyright (C) 2008-2020 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file include/thread
 *  This is a Standard C++ Library header.
 */

#ifndef _GLIBCXX_THREAD
#define _GLIBCXX_THREAD 1

#pragma GCC system_header

#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else

#include <bits/c++config.h>

#if defined(_GLIBCXX_HAS_GTHREADS)
#include <bits/gthr.h>

#include <chrono> // std::chrono::*
#include <memory> // std::unique_ptr
#include <tuple>  // std::tuple

#if __cplusplus > 201703L
# include <compare>	// std::strong_ordering
# include <stop_token>	// std::stop_source, std::stop_token, std::nostopstate
#endif

#ifdef _GLIBCXX_USE_NANOSLEEP
# include <cerrno>  // errno, EINTR
# include <time.h>  // nanosleep
#endif

#include <bits/functional_hash.h> // std::hash
#include <bits/invoke.h>	  // std::__invoke

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @defgroup threads Threads
   * @ingroup concurrency
   *
   * Classes for thread support.
   * @{
   */

  /// thread
  class thread
  {
  public:
    // Abstract base class for types that wrap arbitrary functors to be
    // invoked in the new thread of execution.
    struct _State
    {
      virtual ~_State();
      virtual void _M_run() = 0;
    };
    using _State_ptr = unique_ptr<_State>;

    typedef __gthread_t			native_handle_type;

    /// thread::id
    class id
    {
      native_handle_type	_M_thread;

    public:
      id() noexcept : _M_thread() { }

      explicit
      id(native_handle_type __id) : _M_thread(__id) { }

    private:
      friend class thread;
      friend class hash<id>;

      friend bool
      operator==(id __x, id __y) noexcept;

#if __cpp_lib_three_way_comparison
      friend strong_ordering
      operator<=>(id __x, id __y) noexcept;
#else
      friend bool
      operator<(id __x, id __y) noexcept;
#endif

      template<class _CharT, class _Traits>
	friend basic_ostream<_CharT, _Traits>&
	operator<<(basic_ostream<_CharT, _Traits>& __out, id __id);
    };

  private:
    id				_M_id;

    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // 2097.  packaged_task constructors should be constrained
    // 3039. Unnecessary decay in thread and packaged_task
    template<typename _Tp>
      using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>;

  public:
    thread() noexcept = default;

    template<typename _Callable, typename... _Args,
	     typename = _Require<__not_same<_Callable>>>
      explicit
      thread(_Callable&& __f, _Args&&... __args)
      {
	static_assert( __is_invocable<typename decay<_Callable>::type,
				      typename decay<_Args>::type...>::value,
	  "std::thread arguments must be invocable after conversion to rvalues"
	  );

#ifdef GTHR_ACTIVE_PROXY
	// Create a reference to pthread_create, not just the gthr weak symbol.
	auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
#else
	auto __depend = nullptr;
#endif
	// A call wrapper holding tuple{DECAY_COPY(__f), DECAY_COPY(__args)...}
	using _Invoker_type = _Invoker<__decayed_tuple<_Callable, _Args...>>;

	_M_start_thread(_S_make_state<_Invoker_type>(
	      std::forward<_Callable>(__f), std::forward<_Args>(__args)...),
	    __depend);
      }

    ~thread()
    {
      if (joinable())
	std::terminate();
    }

    thread(const thread&) = delete;

    thread(thread&& __t) noexcept
    { swap(__t); }

    thread& operator=(const thread&) = delete;

    thread& operator=(thread&& __t) noexcept
    {
      if (joinable())
	std::terminate();
      swap(__t);
      return *this;
    }

    void
    swap(thread& __t) noexcept
    { std::swap(_M_id, __t._M_id); }

    bool
    joinable() const noexcept
    { return !(_M_id == id()); }

    void
    join();

    void
    detach();

    id
    get_id() const noexcept
    { return _M_id; }

    /** @pre thread is joinable
     */
    native_handle_type
    native_handle()
    { return _M_id._M_thread; }

    // Returns a value that hints at the number of hardware thread contexts.
    static unsigned int
    hardware_concurrency() noexcept;

  private:
    template<typename _Callable>
      struct _State_impl : public _State
      {
	_Callable		_M_func;

	template<typename... _Args>
	  _State_impl(_Args&&... __args)
	  : _M_func{{std::forward<_Args>(__args)...}}
	  { }

	void
	_M_run() { _M_func(); }
      };

    void
    _M_start_thread(_State_ptr, void (*)());

    template<typename _Callable, typename... _Args>
      static _State_ptr
      _S_make_state(_Args&&... __args)
      {
	using _Impl = _State_impl<_Callable>;
	return _State_ptr{new _Impl{std::forward<_Args>(__args)...}};
      }
#if _GLIBCXX_THREAD_ABI_COMPAT
  public:
    struct _Impl_base;
    typedef shared_ptr<_Impl_base>	__shared_base_type;
    struct _Impl_base
    {
      __shared_base_type	_M_this_ptr;
      virtual ~_Impl_base() = default;
      virtual void _M_run() = 0;
    };

  private:
    void
    _M_start_thread(__shared_base_type, void (*)());

    void
    _M_start_thread(__shared_base_type);
#endif

  private:
    // A call wrapper that does INVOKE(forwarded tuple elements...)
    template<typename _Tuple>
      struct _Invoker
      {
	_Tuple _M_t;

	template<typename>
	  struct __result;
	template<typename _Fn, typename... _Args>
	  struct __result<tuple<_Fn, _Args...>>
	  : __invoke_result<_Fn, _Args...>
	  { };

	template<size_t... _Ind>
	  typename __result<_Tuple>::type
	  _M_invoke(_Index_tuple<_Ind...>)
	  { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }

	typename __result<_Tuple>::type
	operator()()
	{
	  using _Indices
	    = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
	  return _M_invoke(_Indices());
	}
      };

    template<typename... _Tp>
      using __decayed_tuple = tuple<typename decay<_Tp>::type...>;

  public:
    // Returns a call wrapper that stores
    // tuple{DECAY_COPY(__callable), DECAY_COPY(__args)...}.
    template<typename _Callable, typename... _Args>
      static _Invoker<__decayed_tuple<_Callable, _Args...>>
      __make_invoker(_Callable&& __callable, _Args&&... __args)
      {
	return { __decayed_tuple<_Callable, _Args...>{
	    std::forward<_Callable>(__callable), std::forward<_Args>(__args)...
	} };
      }
  };

  inline void
  swap(thread& __x, thread& __y) noexcept
  { __x.swap(__y); }

  inline bool
  operator==(thread::id __x, thread::id __y) noexcept
  {
    // pthread_equal is undefined if either thread ID is not valid, so we
    // can't safely use __gthread_equal on default-constructed values (nor
    // the non-zero value returned by this_thread::get_id() for
    // single-threaded programs using GNU libc). Assume EqualityComparable.
    return __x._M_thread == __y._M_thread;
  }

#if __cpp_lib_three_way_comparison
  inline strong_ordering
  operator<=>(thread::id __x, thread::id __y) noexcept
  { return __x._M_thread <=> __y._M_thread; }
#else
  inline bool
  operator!=(thread::id __x, thread::id __y) noexcept
  { return !(__x == __y); }

  inline bool
  operator<(thread::id __x, thread::id __y) noexcept
  {
    // Pthreads doesn't define any way to do this, so we just have to
    // assume native_handle_type is LessThanComparable.
    return __x._M_thread < __y._M_thread;
  }

  inline bool
  operator<=(thread::id __x, thread::id __y) noexcept
  { return !(__y < __x); }

  inline bool
  operator>(thread::id __x, thread::id __y) noexcept
  { return __y < __x; }

  inline bool
  operator>=(thread::id __x, thread::id __y) noexcept
  { return !(__x < __y); }
#endif // __cpp_lib_three_way_comparison

  // DR 889.
  /// std::hash specialization for thread::id.
  template<>
    struct hash<thread::id>
    : public __hash_base<size_t, thread::id>
    {
      size_t
      operator()(const thread::id& __id) const noexcept
      { return std::_Hash_impl::hash(__id._M_thread); }
    };

  template<class _CharT, class _Traits>
    inline basic_ostream<_CharT, _Traits>&
    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
    {
      if (__id == thread::id())
	return __out << "thread::id of a non-executing thread";
      else
	return __out << __id._M_thread;
    }

  /** @namespace std::this_thread
   *  @brief ISO C++ 2011 namespace for interacting with the current thread
   *
   *  C++11 30.3.2 [thread.thread.this] Namespace this_thread.
   */
  namespace this_thread
  {
    /// get_id
    inline thread::id
    get_id() noexcept
    {
#ifdef __GLIBC__
      // For the GNU C library pthread_self() is usable without linking to
      // libpthread.so but returns 0, so we cannot use it in single-threaded
      // programs, because this_thread::get_id() != thread::id{} must be true.
      // We know that pthread_t is an integral type in the GNU C library.
      if (!__gthread_active_p())
	return thread::id(1);
#endif
      return thread::id(__gthread_self());
    }

    /// yield
    inline void
    yield() noexcept
    {
#ifdef _GLIBCXX_USE_SCHED_YIELD
      __gthread_yield();
#endif
    }

    void
    __sleep_for(chrono::seconds, chrono::nanoseconds);

    /// sleep_for
    template<typename _Rep, typename _Period>
      inline void
      sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
      {
	if (__rtime <= __rtime.zero())
	  return;
	auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
#ifdef _GLIBCXX_USE_NANOSLEEP
	__gthread_time_t __ts =
	  {
	    static_cast<std::time_t>(__s.count()),
	    static_cast<long>(__ns.count())
	  };
	while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
	  { }
#else
	__sleep_for(__s, __ns);
#endif
      }

    /// sleep_until
    template<typename _Clock, typename _Duration>
      inline void
      sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
      {
#if __cplusplus > 201703L
	static_assert(chrono::is_clock_v<_Clock>);
#endif
	auto __now = _Clock::now();
	if (_Clock::is_steady)
	  {
	    if (__now < __atime)
	      sleep_for(__atime - __now);
	    return;
	  }
	while (__now < __atime)
	  {
	    sleep_for(__atime - __now);
	    __now = _Clock::now();
	  }
      }
  }

  // @} group threads

#ifdef __cpp_lib_jthread

  class jthread
  {
  public:
    using id = thread::id;
    using native_handle_type = thread::native_handle_type;

    jthread() noexcept
    : _M_stop_source{nostopstate}
    { }

    template<typename _Callable, typename... _Args,
	     typename = enable_if_t<!is_same_v<remove_cvref_t<_Callable>,
					       jthread>>>
      explicit
      jthread(_Callable&& __f, _Args&&... __args)
      : _M_thread{_S_create(_M_stop_source, std::forward<_Callable>(__f),
			    std::forward<_Args>(__args)...)}
      { }

    jthread(const jthread&) = delete;
    jthread(jthread&&) noexcept = default;

    ~jthread()
    {
      if (joinable())
        {
          request_stop();
          join();
        }
    }

    jthread&
    operator=(const jthread&) = delete;

    jthread&
    operator=(jthread&&) noexcept = default;

    void
    swap(jthread& __other) noexcept
    {
      std::swap(_M_stop_source, __other._M_stop_source);
      std::swap(_M_thread, __other._M_thread);
    }

    [[nodiscard]] bool
    joinable() const noexcept
    {
      return _M_thread.joinable();
    }

    void
    join()
    {
      _M_thread.join();
    }

    void
    detach()
    {
      _M_thread.detach();
    }

    [[nodiscard]] id
    get_id() const noexcept
    {
      return _M_thread.get_id();
    }

    [[nodiscard]] native_handle_type
    native_handle()
    {
      return _M_thread.native_handle();
    }

    [[nodiscard]] static unsigned
    hardware_concurrency() noexcept
    {
      return thread::hardware_concurrency();
    }

    [[nodiscard]] stop_source
    get_stop_source() noexcept
    {
      return _M_stop_source;
    }

    [[nodiscard]] stop_token
    get_stop_token() const noexcept
    {
      return _M_stop_source.get_token();
    }

    bool request_stop() noexcept
    {
      return _M_stop_source.request_stop();
    }

    friend void swap(jthread& __lhs, jthread& __rhs) noexcept
    {
      __lhs.swap(__rhs);
    }

  private:
    template<typename _Callable, typename... _Args>
      static thread
      _S_create(stop_source& __ssrc, _Callable&& __f, _Args&&... __args)
      {
	if constexpr(is_invocable_v<decay_t<_Callable>, stop_token,
				    decay_t<_Args>...>)
	  return thread{std::forward<_Callable>(__f), __ssrc.get_token(),
			std::forward<_Args>(__args)...};
	else
	  {
	    static_assert(is_invocable_v<decay_t<_Callable>,
					 decay_t<_Args>...>,
			  "std::thread arguments must be invocable after"
			  " conversion to rvalues");
	    return thread{std::forward<_Callable>(__f),
			  std::forward<_Args>(__args)...};
	  }
      }

    stop_source _M_stop_source;
    thread _M_thread;
  };
#endif // __cpp_lib_jthread
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // _GLIBCXX_HAS_GTHREADS
#endif // C++11
#endif // _GLIBCXX_THREAD
