void ThreadPool::shutDown() { Lock(poolLock); ThreadInfo *p; // note: do not terminate thread 0 (main thread) in this loop for (unsigned i = 1; i < nThreads; i++) { p = data[i]; // All threads should be idle when this function is called. if (p->state == ThreadInfo::Idle) { // Set the thread to the terminating state that will force thread // procedure exit p->state = ThreadInfo::Terminating; // unblock the thread p->signal(); } // wait for the thread to terminate #ifdef _WIN32 WaitForSingleObject(p->thread_id,INFINITE); #else void *value_ptr; pthread_join(p->thread_id,&value_ptr); #endif // Free thread data delete p; } // now free main thread data delete data[0]->work; delete data[0]; // main thread structure Unlock(poolLock); }
void ThreadPool::resize(unsigned n, SearchController *controller) { if (n >= 1 && n < Constants::MaxCPUs && n != nThreads) { lock(); #ifdef NUMA topo.recalc(); #endif if (n>nThreads) { // growing while (n > nThreads) { data[nThreads] = new ThreadInfo(this,nThreads); nThreads++; } } else { // shrinking while (n < nThreads) { ThreadInfo *p = data[nThreads-1]; p->state = ThreadInfo::Terminating; if (p->state == ThreadInfo::Idle) { p->signal(); // unblock thread & exit thread proc // wait for thread exit #ifdef _WIN32 WaitForSingleObject(p->thread_id,INFINITE); #else void *value_ptr; pthread_join(p->thread_id,&value_ptr); #endif } delete p; data[nThreads] = NULL; --nThreads; } } unlock(); } ASSERT(nThreads == n); availableMask = (n == 64) ? 0xffffffffffffffffULL : (1ULL << n)-1; }
void ThreadPool::checkIn(ThreadInfo *ti) { #ifdef _THREAD_TRACE { std::ostringstream s; s << "checkIn: " << ti->index << " master=" << ti->work->split->master->index << '\0'; log(s.str()); } #endif Lock(poolLock); SplitPoint *split = ti->work->split; ThreadInfo *parent = split->master; Search *parentSearch = parent->work; // lock parent's stack Lock(parentSearch->splitLock); split->lock(); // dissociate the thread from the parent ArasanSet<ThreadInfo *,Constants::MaxCPUs> &slaves = split->slaves; // remove ti from the list of slave threads in the parent #ifdef _THREAD_TRACE { std::ostringstream s; s << "removing slave thread " << ti->index << " from master " << split->master->index << '\0'; log(s.str()); } #endif #ifdef _DEBUG ASSERT(slaves.remove(ti)); #else slaves.remove(ti); #endif const int remaining = slaves.size(); const bool top = split - parentSearch->splitStack + 1 == parentSearch->activeSplitPoints; #ifdef _THREAD_TRACE { std::ostringstream s; s << "after checkIn: " << ti->index << " remaining: " << remaining << " top=" << top << '\0'; log(s.str()); } #endif if (!remaining && top) { // all slave threads are completed, so signal parent that it // can exit its wait state and pop the split stack. ASSERT(parent); // Set parent state to Working before it even wakes up. This // ensures it will not be allocated to another split point. parent->state = ThreadInfo::Working; activeMask |= (1ULL << parent->index); #ifdef _THREAD_TRACE std::ostringstream s; s << "thread " << ti->index << " signaling parent (" << parent->index << ")" << " parent state=" << parent->state << '\0'; log(s.str()); #endif ASSERT(parent->index != ti->index); #ifdef _THREAD_TRACE log("signal",parent->index); #endif parent->signal(); } // ensure we we will wait when back in the idle loop ti->reset(); split->unlock(); Unlock(parentSearch->splitLock); Unlock(poolLock); }