GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 16 / 0 / 16
Functions: 100.0% 7 / 0 / 7
Branches: -% 0 / 0 / 0

libs/capy/include/boost/capy/ex/thread_pool.hpp
Line Branch Exec Source
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 <boost/capy/coro.hpp>
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 via stop token. Threads will
84 finish their current work item before exiting. Does not
85 wait for 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 58 executor_type(thread_pool& pool) noexcept
117 58 : pool_(&pool)
118 {
119 58 }
120
121 public:
122 /// Default construct a null executor.
123 executor_type() = default;
124
125 /// Return the underlying thread pool.
126 thread_pool&
127 27 context() const noexcept
128 {
129 27 return *pool_;
130 }
131
132 /// Notify that work has started (no-op for thread pools).
133 void
134 4 on_work_started() const noexcept
135 {
136 4 }
137
138 /// Notify that work has finished (no-op for thread pools).
139 void
140 4 on_work_finished() const noexcept
141 {
142 4 }
143
144 /** Dispatch a coroutine for execution.
145
146 Posts the coroutine to the thread pool and returns
147 immediately. The caller should suspend after calling
148 this function.
149
150 @param h The coroutine handle to execute.
151
152 @return A noop coroutine handle to resume.
153 */
154 coro
155 3 dispatch(coro h) const
156 {
157 3 post(h);
158 3 return std::noop_coroutine();
159 }
160
161 /** Post a coroutine to the thread pool.
162
163 The coroutine will be resumed on one of the pool's
164 worker threads.
165
166 @param h The coroutine handle to execute.
167 */
168 BOOST_CAPY_DECL
169 void
170 post(coro h) const;
171
172 /// Return true if two executors refer to the same thread pool.
173 bool
174 13 operator==(executor_type const& other) const noexcept
175 {
176 13 return pool_ == other.pool_;
177 }
178 };
179
180 //------------------------------------------------------------------------------
181
182 inline
183 auto
184 58 thread_pool::
185 get_executor() const noexcept ->
186 executor_type
187 {
188 58 return executor_type(const_cast<thread_pool&>(*this));
189 }
190
191 } // capy
192 } // boost
193
194 #endif
195