| 57 | } |
| 58 | |
| 59 | void thread_executor::shutdown() { |
| 60 | const auto abort = m_atomic_abort.exchange(true, std::memory_order_relaxed); |
| 61 | if (abort) { |
| 62 | return; // shutdown had been called before. |
| 63 | } |
| 64 | |
| 65 | std::unique_lock<std::mutex> lock(m_lock); |
| 66 | m_abort = true; |
| 67 | m_condition.wait(lock, [this] { |
| 68 | return m_workers.empty(); |
| 69 | }); |
| 70 | |
| 71 | if (m_last_retired.empty()) { |
| 72 | return; |
| 73 | } |
| 74 | |
| 75 | assert(m_last_retired.size() == 1); |
| 76 | m_last_retired.front().join(); |
| 77 | m_last_retired.clear(); |
| 78 | } |
| 79 | |
| 80 | void thread_executor::retire_worker(std::list<details::thread>::iterator it) { |
| 81 | std::unique_lock<std::mutex> lock(m_lock); |