LCOV - code coverage report
Current view: top level - capy/ex - thread_pool.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 16 16
Test Date: 2026-02-17 18:14:47 Functions: 100.0 % 7 7

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : // Copyright (c) 2026 Michael Vandeberg
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/boostorg/capy
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_CAPY_EX_THREAD_POOL_HPP
      12                 : #define BOOST_CAPY_EX_THREAD_POOL_HPP
      13                 : 
      14                 : #include <boost/capy/detail/config.hpp>
      15                 : #include <coroutine>
      16                 : #include <boost/capy/ex/execution_context.hpp>
      17                 : #include <cstddef>
      18                 : #include <string_view>
      19                 : 
      20                 : namespace boost {
      21                 : namespace capy {
      22                 : 
      23                 : /** A pool of threads for executing work concurrently.
      24                 : 
      25                 :     Use this when you need to run coroutines on multiple threads
      26                 :     without the overhead of creating and destroying threads for
      27                 :     each task. Work items are distributed across the pool using
      28                 :     a shared queue.
      29                 : 
      30                 :     @par Thread Safety
      31                 :     Distinct objects: Safe.
      32                 :     Shared objects: Unsafe.
      33                 : 
      34                 :     @par Example
      35                 :     @code
      36                 :     thread_pool pool(4);  // 4 worker threads
      37                 :     auto ex = pool.get_executor();
      38                 :     ex.post(some_coroutine);
      39                 :     // pool destructor waits for all work to complete
      40                 :     @endcode
      41                 : */
      42                 : class BOOST_CAPY_DECL
      43                 :     thread_pool
      44                 :     : public execution_context
      45                 : {
      46                 :     class impl;
      47                 :     impl* impl_;
      48                 : 
      49                 : public:
      50                 :     class executor_type;
      51                 : 
      52                 :     /** Destroy the thread pool.
      53                 : 
      54                 :         Signals all worker threads to stop, waits for them to
      55                 :         finish, and destroys any pending work items.
      56                 :     */
      57                 :     ~thread_pool();
      58                 : 
      59                 :     /** Construct a thread pool.
      60                 : 
      61                 :         Creates a pool with the specified number of worker threads.
      62                 :         If `num_threads` is zero, the number of threads is set to
      63                 :         the hardware concurrency, or one if that cannot be determined.
      64                 : 
      65                 :         @param num_threads The number of worker threads, or zero
      66                 :             for automatic selection.
      67                 : 
      68                 :         @param thread_name_prefix The prefix for worker thread names.
      69                 :             Thread names appear as "{prefix}0", "{prefix}1", etc.
      70                 :             The prefix is truncated to 12 characters. Defaults to
      71                 :             "capy-pool-".
      72                 :     */
      73                 :     explicit
      74                 :     thread_pool(
      75                 :         std::size_t num_threads = 0,
      76                 :         std::string_view thread_name_prefix = "capy-pool-");
      77                 : 
      78                 :     thread_pool(thread_pool const&) = delete;
      79                 :     thread_pool& operator=(thread_pool const&) = delete;
      80                 : 
      81                 :     /** Request all worker threads to stop.
      82                 : 
      83                 :         Signals all threads to exit. Threads will finish their
      84                 :         current work item before exiting. Does not wait for
      85                 :         threads to exit.
      86                 :     */
      87                 :     void
      88                 :     stop() noexcept;
      89                 : 
      90                 :     /** Return an executor for this thread pool.
      91                 : 
      92                 :         @return An executor associated with this thread pool.
      93                 :     */
      94                 :     executor_type
      95                 :     get_executor() const noexcept;
      96                 : };
      97                 : 
      98                 : //------------------------------------------------------------------------------
      99                 : 
     100                 : /** An executor that submits work to a thread_pool.
     101                 : 
     102                 :     Executors are lightweight handles that can be copied and stored.
     103                 :     All copies refer to the same underlying thread pool.
     104                 : 
     105                 :     @par Thread Safety
     106                 :     Distinct objects: Safe.
     107                 :     Shared objects: Safe.
     108                 : */
     109                 : class thread_pool::executor_type
     110                 : {
     111                 :     friend class thread_pool;
     112                 : 
     113                 :     thread_pool* pool_ = nullptr;
     114                 : 
     115                 :     explicit
     116 HIT          61 :     executor_type(thread_pool& pool) noexcept
     117              61 :         : pool_(&pool)
     118                 :     {
     119              61 :     }
     120                 : 
     121                 : public:
     122                 :     /// Default construct a null executor.
     123                 :     executor_type() = default;
     124                 : 
     125                 :     /// Return the underlying thread pool.
     126                 :     thread_pool&
     127              29 :     context() const noexcept
     128                 :     {
     129              29 :         return *pool_;
     130                 :     }
     131                 : 
     132                 :     /// Notify that work has started (no-op for thread pools).
     133                 :     void
     134               6 :     on_work_started() const noexcept
     135                 :     {
     136               6 :     }
     137                 : 
     138                 :     /// Notify that work has finished (no-op for thread pools).
     139                 :     void
     140               6 :     on_work_finished() const noexcept
     141                 :     {
     142               6 :     }
     143                 : 
     144                 :     /** Dispatch a coroutine for execution.
     145                 : 
     146                 :         Posts the coroutine to the thread pool for execution on a
     147                 :         worker thread and returns `std::noop_coroutine()`. Thread
     148                 :         pools never execute inline because no single thread "owns"
     149                 :         the pool.
     150                 : 
     151                 :         @param h The coroutine handle to execute.
     152                 : 
     153                 :         @return `std::noop_coroutine()` always.
     154                 :     */
     155                 :     std::coroutine_handle<>
     156               6 :     dispatch(std::coroutine_handle<> h) const
     157                 :     {
     158               6 :         post(h);
     159               6 :         return std::noop_coroutine();
     160                 :     }
     161                 : 
     162                 :     /** Post a coroutine to the thread pool.
     163                 : 
     164                 :         The coroutine will be resumed on one of the pool's
     165                 :         worker threads.
     166                 : 
     167                 :         @param h The coroutine handle to execute.
     168                 :     */
     169                 :     BOOST_CAPY_DECL
     170                 :     void
     171                 :     post(std::coroutine_handle<> h) const;
     172                 : 
     173                 :     /// Return true if two executors refer to the same thread pool.
     174                 :     bool
     175              13 :     operator==(executor_type const& other) const noexcept
     176                 :     {
     177              13 :         return pool_ == other.pool_;
     178                 :     }
     179                 : };
     180                 : 
     181                 : //------------------------------------------------------------------------------
     182                 : 
     183                 : inline
     184                 : auto
     185              61 : thread_pool::
     186                 : get_executor() const noexcept ->
     187                 :     executor_type
     188                 : {
     189              61 :     return executor_type(const_cast<thread_pool&>(*this));
     190                 : }
     191                 : 
     192                 : } // capy
     193                 : } // boost
     194                 : 
     195                 : #endif
        

Generated by: LCOV version 2.3