GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 88.2% 60 / 0 / 68
Functions: 87.5% 14 / 0 / 16
Branches: 72.4% 21 / 0 / 29

libs/capy/src/ex/thread_pool.cpp
Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/capy
8 //
9
10 #include <boost/capy/ex/thread_pool.hpp>
11 #include <boost/capy/detail/intrusive.hpp>
12 #include <condition_variable>
13 #include <mutex>
14 #include <stop_token>
15 #include <thread>
16 #include <vector>
17
18 namespace boost {
19 namespace capy {
20
21 //------------------------------------------------------------------------------
22
23 class thread_pool::impl
24 {
25 struct work : detail::intrusive_queue<work>::node
26 {
27 coro h_;
28
29 118 explicit work(coro h) noexcept
30 118 : h_(h)
31 {
32 118 }
33
34 118 void run()
35 {
36 118 auto h = h_;
37
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
118 delete this;
38
1/1
✓ Branch 1 taken 118 times.
118 h.resume();
39 118 }
40
41 void destroy()
42 {
43 delete this;
44 }
45 };
46
47 std::mutex mutex_;
48 std::condition_variable_any cv_;
49 detail::intrusive_queue<work> q_;
50 std::vector<std::jthread> threads_;
51 std::size_t num_threads_;
52 std::once_flag start_flag_;
53
54 public:
55 51 ~impl()
56 {
57 51 stop();
58 51 threads_.clear();
59
60
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
51 while(auto* w = q_.pop())
61 w->destroy();
62 51 }
63
64 explicit
65 51 impl(std::size_t num_threads)
66 51 : num_threads_(num_threads)
67 {
68
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 50 times.
51 if(num_threads_ == 0)
69 1 num_threads_ = std::thread::hardware_concurrency();
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if(num_threads_ == 0)
71 num_threads_ = 1;
72 51 }
73
74 void
75 118 post(coro h)
76 {
77 118 ensure_started();
78 118 auto* w = new work(h);
79 {
80
1/1
✓ Branch 1 taken 118 times.
118 std::lock_guard<std::mutex> lock(mutex_);
81 118 q_.push(w);
82 118 }
83 118 cv_.notify_one();
84 118 }
85
86 void
87 51 stop() noexcept
88 {
89
2/2
✓ Branch 5 taken 31 times.
✓ Branch 6 taken 51 times.
82 for (auto& t : threads_)
90 31 t.request_stop();
91 51 cv_.notify_all();
92 51 }
93
94 private:
95 void
96 118 ensure_started()
97 {
98
1/1
✓ Branch 1 taken 118 times.
118 std::call_once(start_flag_, [this]{
99 19 threads_.reserve(num_threads_);
100
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 19 times.
50 for(std::size_t i = 0; i < num_threads_; ++i)
101
2/2
✓ Branch 2 taken 31 times.
✓ Branch 7 taken 31 times.
62 threads_.emplace_back([this](std::stop_token st){ run(st); });
102 19 });
103 118 }
104
105 void
106 31 run(std::stop_token st)
107 {
108 for(;;)
109 {
110 149 work* w = nullptr;
111 {
112
1/1
✓ Branch 1 taken 149 times.
149 std::unique_lock<std::mutex> lock(mutex_);
113
3/3
✓ Branch 2 taken 149 times.
✓ Branch 5 taken 31 times.
✓ Branch 6 taken 118 times.
332 if(!cv_.wait(lock, st, [this]{ return !q_.empty(); }))
114 62 return;
115 118 w = q_.pop();
116 149 }
117 118 w->run();
118 118 }
119 }
120 };
121
122 //------------------------------------------------------------------------------
123
124 51 thread_pool::
125 ~thread_pool()
126 {
127 51 shutdown();
128 51 destroy();
129
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 delete impl_;
130 51 }
131
132 51 thread_pool::
133 51 thread_pool(std::size_t num_threads)
134
2/4
✓ Branch 2 taken 51 times.
✓ Branch 5 taken 51 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
51 : impl_(new impl(num_threads))
135 {
136 51 }
137
138 void
139 thread_pool::
140 stop() noexcept
141 {
142 impl_->stop();
143 }
144
145 //------------------------------------------------------------------------------
146
147 void
148 118 thread_pool::executor_type::
149 post(coro h) const
150 {
151 118 pool_->impl_->post(h);
152 118 }
153
154 } // capy
155 } // boost
156