LCOV - code coverage report
Current view: top level - 11/bits - std_thread.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 39 41 95.1 %
Date: 2025-08-24 09:11:10 Functions: 59 77 76.6 %

          Line data    Source code
       1             : // std::thread declarations -*- C++ -*-
       2             : 
       3             : // Copyright (C) 2008-2021 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 bits/std_thread.h
      26             :  *  This is an internal header file, included by other library headers.
      27             :  *  Do not attempt to use it directly. @headername{thread}
      28             :  */
      29             : 
      30             : #ifndef _GLIBCXX_THREAD_H
      31             : #define _GLIBCXX_THREAD_H 1
      32             : 
      33             : #pragma GCC system_header
      34             : 
      35             : #if __cplusplus >= 201103L
      36             : #include <bits/c++config.h>
      37             : 
      38             : #include <exception>              // std::terminate
      39             : #include <iosfwd>         // std::basic_ostream
      40             : #include <tuple>          // std::tuple
      41             : #include <bits/functional_hash.h> // std::hash
      42             : #include <bits/invoke.h>  // std::__invoke
      43             : #include <bits/refwrap.h>       // not required, but helpful to users
      44             : #include <bits/unique_ptr.h>      // std::unique_ptr
      45             : 
      46             : #ifdef _GLIBCXX_HAS_GTHREADS
      47             : # include <bits/gthr.h>
      48             : #else
      49             : # include <errno.h>
      50             : # include <bits/functexcept.h>
      51             : #endif
      52             : 
      53             : namespace std _GLIBCXX_VISIBILITY(default)
      54             : {
      55             : _GLIBCXX_BEGIN_NAMESPACE_VERSION
      56             : 
      57             :   /** @addtogroup threads
      58             :    *  @{
      59             :    */
      60             : 
      61             :   /// thread
      62             :   class thread
      63             :   {
      64             :   public:
      65             : #ifdef _GLIBCXX_HAS_GTHREADS
      66             :     // Abstract base class for types that wrap arbitrary functors to be
      67             :     // invoked in the new thread of execution.
      68             :     struct _State
      69             :     {
      70             :       virtual ~_State();
      71             :       virtual void _M_run() = 0;
      72             :     };
      73             :     using _State_ptr = unique_ptr<_State>;
      74             : 
      75             :     using native_handle_type = __gthread_t;
      76             : #else
      77             :     using native_handle_type = int;
      78             : #endif
      79             : 
      80             :     /// thread::id
      81             :     class id
      82             :     {
      83             :       native_handle_type        _M_thread;
      84             : 
      85             :     public:
      86       29417 :       id() noexcept : _M_thread() { }
      87             : 
      88             :       explicit
      89        1035 :       id(native_handle_type __id) : _M_thread(__id) { }
      90             : 
      91             :     private:
      92             :       friend class thread;
      93             :       friend struct hash<id>;
      94             : 
      95             :       friend bool
      96             :       operator==(id __x, id __y) noexcept;
      97             : 
      98             : #if __cpp_lib_three_way_comparison
      99             :       friend strong_ordering
     100             :       operator<=>(id __x, id __y) noexcept;
     101             : #else
     102             :       friend bool
     103             :       operator<(id __x, id __y) noexcept;
     104             : #endif
     105             : 
     106             :       template<class _CharT, class _Traits>
     107             :         friend basic_ostream<_CharT, _Traits>&
     108             :         operator<<(basic_ostream<_CharT, _Traits>& __out, id __id);
     109             :     };
     110             : 
     111             :   private:
     112             :     id                          _M_id;
     113             : 
     114             :     // _GLIBCXX_RESOLVE_LIB_DEFECTS
     115             :     // 2097.  packaged_task constructors should be constrained
     116             :     // 3039. Unnecessary decay in thread and packaged_task
     117             :     template<typename _Tp>
     118             :       using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>;
     119             : 
     120             :   public:
     121        1603 :     thread() noexcept = default;
     122             : 
     123             : #ifdef _GLIBCXX_HAS_GTHREADS
     124             :     template<typename _Callable, typename... _Args,
     125             :              typename = _Require<__not_same<_Callable>>>
     126             :       explicit
     127        1366 :       thread(_Callable&& __f, _Args&&... __args)
     128        1366 :       {
     129             :         static_assert( __is_invocable<typename decay<_Callable>::type,
     130             :                                       typename decay<_Args>::type...>::value,
     131             :           "std::thread arguments must be invocable after conversion to rvalues"
     132             :           );
     133             : 
     134             : #ifdef GTHR_ACTIVE_PROXY
     135             :         // Create a reference to pthread_create, not just the gthr weak symbol.
     136             :         auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
     137             : #else
     138        1366 :         auto __depend = nullptr;
     139             : #endif
     140             :         using _Wrapper = _Call_wrapper<_Callable, _Args...>;
     141             :         // Create a call wrapper with DECAY_COPY(__f) as its target object
     142             :         // and DECAY_COPY(__args)... as its bound argument entities.
     143        1366 :         _M_start_thread(_State_ptr(new _State_impl<_Wrapper>(
     144        1366 :               std::forward<_Callable>(__f), std::forward<_Args>(__args)...)),
     145             :             __depend);
     146        1366 :       }
     147             : #endif // _GLIBCXX_HAS_GTHREADS
     148             : 
     149        2930 :     ~thread()
     150             :     {
     151        2930 :       if (joinable())
     152           0 :         std::terminate();
     153        2930 :     }
     154             : 
     155             :     thread(const thread&) = delete;
     156             : 
     157           1 :     thread(thread&& __t) noexcept
     158           1 :     { swap(__t); }
     159             : 
     160             :     thread& operator=(const thread&) = delete;
     161             : 
     162        1326 :     thread& operator=(thread&& __t) noexcept
     163             :     {
     164        1326 :       if (joinable())
     165           0 :         std::terminate();
     166        1326 :       swap(__t);
     167        1326 :       return *this;
     168             :     }
     169             : 
     170             :     void
     171        1327 :     swap(thread& __t) noexcept
     172        1327 :     { std::swap(_M_id, __t._M_id); }
     173             : 
     174             :     bool
     175       25033 :     joinable() const noexcept
     176       25033 :     { return !(_M_id == id()); }
     177             : 
     178             :     void
     179             :     join();
     180             : 
     181             :     void
     182             :     detach();
     183             : 
     184             :     id
     185        1035 :     get_id() const noexcept
     186        1035 :     { return _M_id; }
     187             : 
     188             :     /** @pre thread is joinable
     189             :      */
     190             :     native_handle_type
     191             :     native_handle()
     192             :     { return _M_id._M_thread; }
     193             : 
     194             :     // Returns a value that hints at the number of hardware thread contexts.
     195             :     static unsigned int
     196             :     hardware_concurrency() noexcept;
     197             : 
     198             : #ifdef _GLIBCXX_HAS_GTHREADS
     199             :   private:
     200             :     template<typename _Callable>
     201             :       struct _State_impl : public _State
     202             :       {
     203             :         _Callable               _M_func;
     204             : 
     205             :         template<typename... _Args>
     206        1366 :           _State_impl(_Args&&... __args)
     207        1366 :           : _M_func(std::forward<_Args>(__args)...)
     208        1366 :           { }
     209             : 
     210             :         void
     211        1366 :         _M_run() { _M_func(); }
     212             :       };
     213             : 
     214             :     void
     215             :     _M_start_thread(_State_ptr, void (*)());
     216             : 
     217             : #if _GLIBCXX_THREAD_ABI_COMPAT
     218             :   public:
     219             :     struct _Impl_base;
     220             :     typedef shared_ptr<_Impl_base>        __shared_base_type;
     221             :     struct _Impl_base
     222             :     {
     223             :       __shared_base_type        _M_this_ptr;
     224             :       virtual ~_Impl_base() = default;
     225             :       virtual void _M_run() = 0;
     226             :     };
     227             : 
     228             :   private:
     229             :     void
     230             :     _M_start_thread(__shared_base_type, void (*)());
     231             : 
     232             :     void
     233             :     _M_start_thread(__shared_base_type);
     234             : #endif
     235             : 
     236             :   private:
     237             :     // A call wrapper that does INVOKE(forwarded tuple elements...)
     238             :     template<typename _Tuple>
     239             :       struct _Invoker
     240             :       {
     241             :         template<typename... _Args>
     242             :           explicit
     243        1366 :           _Invoker(_Args&&... __args)
     244        1366 :           : _M_t(std::forward<_Args>(__args)...)
     245        1366 :           { }
     246             : 
     247             :         _Tuple _M_t;
     248             : 
     249             :         template<typename>
     250             :           struct __result;
     251             :         template<typename _Fn, typename... _Args>
     252             :           struct __result<tuple<_Fn, _Args...>>
     253             :           : __invoke_result<_Fn, _Args...>
     254             :           { };
     255             : 
     256             :         template<size_t... _Ind>
     257             :           typename __result<_Tuple>::type
     258        1366 :           _M_invoke(_Index_tuple<_Ind...>)
     259        1366 :           { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
     260             : 
     261             :         typename __result<_Tuple>::type
     262        1366 :         operator()()
     263             :         {
     264             :           using _Indices
     265             :             = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
     266        1366 :           return _M_invoke(_Indices());
     267             :         }
     268             :       };
     269             : 
     270             :   public:
     271             :     template<typename... _Tp>
     272             :       using _Call_wrapper = _Invoker<tuple<typename decay<_Tp>::type...>>;
     273             : #endif // _GLIBCXX_HAS_GTHREADS
     274             :   };
     275             : 
     276             : #ifndef _GLIBCXX_HAS_GTHREADS
     277             :   inline void thread::join() { std::__throw_system_error(EINVAL); }
     278             :   inline void thread::detach() { std::__throw_system_error(EINVAL); }
     279             :   inline unsigned int thread::hardware_concurrency() noexcept { return 0; }
     280             : #endif
     281             : 
     282             :   inline void
     283             :   swap(thread& __x, thread& __y) noexcept
     284             :   { __x.swap(__y); }
     285             : 
     286             :   inline bool
     287       25073 :   operator==(thread::id __x, thread::id __y) noexcept
     288             :   {
     289             :     // pthread_equal is undefined if either thread ID is not valid, so we
     290             :     // can't safely use __gthread_equal on default-constructed values (nor
     291             :     // the non-zero value returned by this_thread::get_id() for
     292             :     // single-threaded programs using GNU libc). Assume EqualityComparable.
     293       25073 :     return __x._M_thread == __y._M_thread;
     294             :   }
     295             : 
     296             :   // N.B. other comparison operators are defined in <thread>
     297             : 
     298             :   // DR 889.
     299             :   /// std::hash specialization for thread::id.
     300             :   template<>
     301             :     struct hash<thread::id>
     302             :     : public __hash_base<size_t, thread::id>
     303             :     {
     304             :       size_t
     305             :       operator()(const thread::id& __id) const noexcept
     306             :       { return std::_Hash_impl::hash(__id._M_thread); }
     307             :     };
     308             : 
     309             :   namespace this_thread
     310             :   {
     311             :     /// this_thread::get_id
     312             :     inline thread::id
     313        1035 :     get_id() noexcept
     314             :     {
     315             : #ifndef _GLIBCXX_HAS_GTHREADS
     316             :       return thread::id(1);
     317             : #elif defined _GLIBCXX_NATIVE_THREAD_ID
     318        1035 :       return thread::id(_GLIBCXX_NATIVE_THREAD_ID);
     319             : #else
     320             :       return thread::id(__gthread_self());
     321             : #endif
     322             :     }
     323             : 
     324             :     /// this_thread::yield
     325             :     inline void
     326             :     yield() noexcept
     327             :     {
     328             : #if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
     329             :       __gthread_yield();
     330             : #endif
     331             :     }
     332             : 
     333             :   } // namespace this_thread
     334             : 
     335             :   /// @}
     336             : 
     337             : _GLIBCXX_END_NAMESPACE_VERSION
     338             : } // namespace
     339             : #endif // C++11
     340             : 
     341             : #endif // _GLIBCXX_THREAD_H

Generated by: LCOV version 1.14