- // If we are not searching, wait for a condition to be signaled instead of
- // wasting CPU time polling for work.
- while ((!searching && Threads.sleepWhileIdle) || exit)
- {
- if (exit)
- {
- assert(!this_sp);
- return;
- }
-
- // Grab the lock to avoid races with Thread::notify_one()
- mutex.lock();
-
- // If we are master and all slaves have finished then exit idle_loop
- if (this_sp && !this_sp->slavesMask)
- {
- mutex.unlock();
- break;
- }
-
- // Do sleep after retesting sleep conditions under lock protection, in
- // particular we need to avoid a deadlock in case a master thread has,
- // in the meanwhile, allocated us and sent the notify_one() call before
- // we had the chance to grab the lock.
- if (!searching && !exit)
- sleepCondition.wait(mutex);
-
- mutex.unlock();
- }
-
- // If this thread has been assigned work, launch a search
- if (searching)
- {
- assert(!exit);
-
- Threads.mutex.lock();
-
- assert(searching);
- SplitPoint* sp = activeSplitPoint;
-
- Threads.mutex.unlock();
-
- Stack ss[MAX_PLY_PLUS_2];
- Position pos(*sp->pos, this);
-
- memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
- (ss+1)->splitPoint = sp;
-
- sp->mutex.lock();
-
- assert(activePosition == NULL);
-
- activePosition = &pos;
-
- switch (sp->nodeType) {
- case Root:
- search<SplitPointRoot>(pos, ss+1, sp->alpha, sp->beta, sp->depth);
- break;
- case PV:
- search<SplitPointPV>(pos, ss+1, sp->alpha, sp->beta, sp->depth);
- break;
- case NonPV:
- search<SplitPointNonPV>(pos, ss+1, sp->alpha, sp->beta, sp->depth);
- break;
- default:
- assert(false);
- }
-
- assert(searching);
-
- searching = false;
- activePosition = NULL;
- sp->slavesMask &= ~(1ULL << idx);
- sp->nodes += pos.nodes_searched();
-
- // Wake up master thread so to allow it to return from the idle loop
- // in case we are the last slave of the split point.
- if ( Threads.sleepWhileIdle
- && this != sp->masterThread
- && !sp->slavesMask)
- {
- assert(!sp->masterThread->searching);
- sp->masterThread->notify_one();
- }
-
- // After releasing the lock we cannot access anymore any SplitPoint
- // related data in a safe way becuase it could have been released under
- // our feet by the sp master. Also accessing other Thread objects is
- // unsafe because if we are exiting there is a chance are already freed.
- sp->mutex.unlock();
- }
-
- // If this thread is the master of a split point and all slaves have finished
- // their work at this split point, return from the idle loop.
- if (this_sp && !this_sp->slavesMask)
- {
- this_sp->mutex.lock();
- bool finished = !this_sp->slavesMask; // Retest under lock protection
- this_sp->mutex.unlock();
- if (finished)
- return;
- }
- }
-}
-
-
-/// check_time() is called by the timer thread when the timer triggers. It is
-/// used to print debug info and, more important, to detect when we are out of
-/// available time and so stop the search.