| 188 | |
| 189 | template <typename Thread> |
| 190 | void ThreadPoolImpl<Thread>::setMaxThreads(size_t value) |
| 191 | { |
| 192 | value = std::min(value, static_cast<size_t>(MAX_THEORETICAL_THREAD_COUNT)); |
| 193 | std::lock_guard lock(mutex); |
| 194 | remaining_pool_capacity.fetch_add(value - max_threads, std::memory_order_relaxed); |
| 195 | |
| 196 | bool need_start_threads = (value > max_threads); |
| 197 | bool need_finish_free_threads = (value < max_free_threads); |
| 198 | |
| 199 | max_threads = value; |
| 200 | max_free_threads = std::min(max_free_threads, max_threads); |
| 201 | |
| 202 | /// We have to also adjust queue size, because it limits the number of scheduled and already running jobs in total. |
| 203 | queue_size = queue_size ? std::max(queue_size, max_threads) : 0; |
| 204 | jobs.reserve(std::min(queue_size, MAX_JOBS_TO_RESERVE)); |
| 205 | |
| 206 | if (need_start_threads) |
| 207 | { |
| 208 | /// Start new threads while there are more scheduled jobs in the queue and the limit `max_threads` is not reached. |
| 209 | startNewThreadsNoLock(); |
| 210 | } |
| 211 | else if (need_finish_free_threads) |
| 212 | { |
| 213 | /// Wake exactly the excess idle threads so they can observe the new limit |
| 214 | /// and exit. We do not call `wakeUpAllIdleThreadsNoLock` here because that |
| 215 | /// would wipe the LIFO stack on every limit adjustment, defeating the |
| 216 | /// purpose of LIFO scheduling. |
| 217 | wakeUpExcessIdleThreadsNoLock(); |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | template <typename Thread> |
| 222 | size_t ThreadPoolImpl<Thread>::getMaxThreads() const |