MCPcopy Create free account
hub / github.com/David-Haim/concurrencpp / balance_work

Method balance_work

source/executors/thread_pool_executor.cpp:197–263  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

195}
196
197void thread_pool_worker::balance_work() {
198 const auto task_count = m_private_queue.size();
199 if (task_count < 2) { // no point in donating tasks
200 return;
201 }
202
203 // we assume all threads but us are idle, we also save at least one task for ourselves
204 const auto max_idle_worker_count = std::min(m_pool_size - 1, task_count - 1);
205 if (max_idle_worker_count == 0) {
206 return; // a thread-pool with a single thread
207 }
208
209 m_parent_pool.find_idle_workers(m_index, m_idle_worker_list, max_idle_worker_count);
210 const auto idle_count = m_idle_worker_list.size();
211 if (idle_count == 0) {
212 return;
213 }
214
215 assert(idle_count <= task_count);
216 const auto total_worker_count = (idle_count + 1); // count ourselves, otherwise we'll donate everything.
217 const auto donation_count = task_count / total_worker_count;
218 auto extra = task_count - donation_count * total_worker_count;
219
220 size_t begin = 0;
221 size_t end = donation_count;
222
223 for (const auto idle_worker_index : m_idle_worker_list) {
224 assert(idle_worker_index != m_index);
225 assert(idle_worker_index < m_pool_size);
226 assert(begin < task_count);
227
228 if (extra != 0) {
229 end++;
230 extra--;
231 }
232
233 assert(end <= task_count);
234
235 auto donation_begin_it = m_private_queue.begin() + begin;
236 auto donation_end_it = m_private_queue.begin() + end;
237
238 assert(donation_begin_it < m_private_queue.end());
239 assert(donation_end_it <= m_private_queue.end());
240
241 m_parent_pool.worker_at(idle_worker_index).enqueue_foreign(donation_begin_it, donation_end_it);
242
243 begin = end;
244 end += donation_count;
245 }
246
247 assert(m_private_queue.size() == task_count);
248
249 // clear everything we've donated.
250 assert(std::all_of(m_private_queue.begin(), m_private_queue.begin() + begin, [](auto& task) {
251 return !static_cast<bool>(task);
252 }));
253
254 assert(std::all_of(m_private_queue.begin() + begin, m_private_queue.end(), [](auto& task) {

Callers

nothing calls this directly

Calls 7

find_idle_workersMethod · 0.80
beginMethod · 0.80
endMethod · 0.80
sizeMethod · 0.45
enqueue_foreignMethod · 0.45
emptyMethod · 0.45
clearMethod · 0.45

Tested by

no test coverage detected