Wait for all currently running tasks to finish
| 350 | |
| 351 | // Wait for all currently running tasks to finish |
| 352 | threadpool_scheduler::~threadpool_scheduler() |
| 353 | { |
| 354 | if (!impl) return; |
| 355 | #ifdef _WIN32 |
| 356 | // Windows kills all threads except one on process exit before calling |
| 357 | // global destructors in DLLs. Waiting for dead threads to exit will likely |
| 358 | // result in deadlocks, so we just exit early if we detect that the process |
| 359 | // is exiting. |
| 360 | auto RtlDllShutdownInProgress = reinterpret_cast<BOOLEAN(WINAPI *)()>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlDllShutdownInProgress")); |
| 361 | if (RtlDllShutdownInProgress && RtlDllShutdownInProgress()) { |
| 362 | # ifndef BROKEN_JOIN_IN_DESTRUCTOR |
| 363 | // We still need to detach the thread handles otherwise the std::thread |
| 364 | // destructor will throw an exception. |
| 365 | for (std::size_t i = 0; i < impl->thread_data.size(); i++) { |
| 366 | try { |
| 367 | impl->thread_data[i].handle.detach(); |
| 368 | } catch (...) {} |
| 369 | } |
| 370 | # endif |
| 371 | return; |
| 372 | } |
| 373 | #endif |
| 374 | |
| 375 | { |
| 376 | std::unique_lock<std::mutex> locked(impl->lock); |
| 377 | |
| 378 | // Signal shutdown |
| 379 | impl->shutdown = true; |
| 380 | |
| 381 | // Wake up any sleeping threads |
| 382 | size_t num_waiters_val = impl->num_waiters.load(std::memory_order_relaxed); |
| 383 | for (std::size_t i = 0; i < num_waiters_val; i++) |
| 384 | impl->waiters[i]->signal(detail::wait_type::task_available); |
| 385 | impl->num_waiters.store(0, std::memory_order_relaxed); |
| 386 | |
| 387 | #ifdef BROKEN_JOIN_IN_DESTRUCTOR |
| 388 | // Wait for the threads to exit |
| 389 | impl->shutdown_num_threads = impl->thread_data.size(); |
| 390 | impl->shutdown_complete_event.wait(locked); |
| 391 | #endif |
| 392 | } |
| 393 | |
| 394 | #ifndef BROKEN_JOIN_IN_DESTRUCTOR |
| 395 | // Wait for the threads to exit |
| 396 | for (std::size_t i = 0; i < impl->thread_data.size(); i++) |
| 397 | impl->thread_data[i].handle.join(); |
| 398 | #endif |
| 399 | } |
| 400 | |
| 401 | // Schedule a task on the thread pool |
| 402 | void threadpool_scheduler::schedule(task_run_handle t) |