void ThreadPoolImpl::Stop() { if (m_ok) { // wait for all threads to idle while (PoolThread::s_sleepCount < m_numThreads) { GIVE_UP_TIME(); } // set invalid flag, then wake them up so they exit their main func m_ok = false; int exited_count; do { pokeIdleThread(); GIVE_UP_TIME(); exited_count = 0; for (int i = 0; i < m_numThreads; i++) { exited_count += m_threads[i].isExited() ? 1 : 0; } } while (exited_count < m_numThreads); // join each thread to cleanup resources for (int i = 0; i < m_numThreads; i++) { m_threads[i].stop(); } } }
ThreadPoolImpl::ThreadPoolImpl(int numThreads) : m_ok(false) , m_referenceCount(1) , m_firstProvider(NULL) , m_lastProvider(NULL) { if (numThreads == 0) numThreads = get_cpu_count(); char *buffer = new char[sizeof(PoolThread) * numThreads]; m_threads = reinterpret_cast<PoolThread*>(buffer); m_numThreads = numThreads; if (m_threads) { m_ok = true; for (int i = 0; i < numThreads; i++) { new (buffer)PoolThread(*this); buffer += sizeof(PoolThread); m_ok = m_ok && m_threads[i].start(); } // Wait for threads to spin up and idle while (PoolThread::s_sleepCount < m_numThreads) { GIVE_UP_TIME(); } } }
void ThreadPool::stopWorkers() { if (m_workers) { m_isActive = false; for (int i = 0; i < m_numWorkers; i++) { while (!(m_sleepBitmap & ((sleepbitmap_t)1 << i))) GIVE_UP_TIME(); m_workers[i].awaken(); m_workers[i].stop(); } } }
void ThreadPoolImpl::waitForAllIdle() { if (!m_ok) return; int id = 0; do { int word = id >> 6; uint64_t bit = 1LL << (id & 63); if (m_sleepMap[word] & bit) { id++; } else { GIVE_UP_TIME(); } } while (id < m_numThreads); }
/* Ensure all threads are either idle, or have made a full * pass through the provider list, ensuring dequeued providers * are safe for deletion. */ void ThreadPoolImpl::FlushProviderList() { for (int i = 0; i < m_numThreads; i++) { m_threads[i].markDirty(); } int i; do { for (i = 0; i < m_numThreads; i++) { if (m_threads[i].isDirty()) { GIVE_UP_TIME(); break; } } } while (i < m_numThreads); }