| 560 | |
| 561 | template <typename Thread> |
| 562 | void ThreadPoolImpl<Thread>::finalize() |
| 563 | { |
| 564 | { |
| 565 | std::lock_guard lock(mutex); |
| 566 | shutdown = true; |
| 567 | |
| 568 | /// scheduleImpl doesn't check for shutdown outside the critical section, |
| 569 | /// so we set remaining_pool_capacity to a large negative value |
| 570 | /// (e.g., -MAX_THEORETICAL_THREAD_COUNT) to signal that no new threads are needed. |
| 571 | /// This effectively prevents any new threads from being started during shutdown. |
| 572 | remaining_pool_capacity.store(-MAX_THEORETICAL_THREAD_COUNT, std::memory_order_relaxed); |
| 573 | |
| 574 | /// Disable thread self-removal from `threads`. Otherwise, if threads remove themselves, |
| 575 | /// the thread.join() operation will fail later in this function. |
| 576 | threads_remove_themselves = false; |
| 577 | |
| 578 | /// Wake up all idle threads so they can see shutdown and exit gracefully. |
| 579 | wakeUpAllIdleThreadsNoLock(); |
| 580 | } |
| 581 | |
| 582 | /// Join all threads before clearing the list |
| 583 | for (auto& thread_ptr : threads) |
| 584 | { |
| 585 | if (thread_ptr) |
| 586 | thread_ptr->join(); |
| 587 | } |
| 588 | |
| 589 | // now it's safe to clear the threads |
| 590 | threads.clear(); |
| 591 | } |
| 592 | |
| 593 | template <typename Thread> |
| 594 | void ThreadPoolImpl<Thread>::addOnDestroyCallback(OnDestroyCallback && callback) |