// which are busy searching the split point at the top of slave's split point
// stack (the "helpful master concept" in YBWC terminology).
-bool Thread::available_to(const Thread* master) const {
+bool Thread::available_to(const Thread* master, bool latejoin) const {
- if (searching)
+ if (searching && !latejoin)
return false;
// Make a local copy to be sure it doesn't become zero under our feet while
// No split points means that the thread is available as a slave for any
// other thread otherwise apply the "helpful master" concept if possible.
- return !size || (splitPoints[size - 1].slavesMask & (1ULL << master->idx));
+ return !size || splitPoints[size - 1].slavesMask.test(master->idx);
}
Thread* ThreadPool::available_slave(const Thread* master) const {
for (const_iterator it = begin(); it != end(); ++it)
- if ((*it)->available_to(master))
+ if ((*it)->available_to(master, false))
return *it;
return NULL;
sp.masterThread = this;
sp.parentSplitPoint = activeSplitPoint;
- sp.slavesMask = 1ULL << idx;
+ sp.slavesMask = 0, sp.slavesMask.set(idx);
sp.depth = depth;
sp.bestValue = *bestValue;
sp.bestMove = *bestMove;
Threads.mutex.lock();
sp.mutex.lock();
+ sp.allowLatejoin = true; // Only set this under lock protection
++splitPointsSize;
activeSplitPoint = &sp;
activePosition = NULL;
if (!Fake)
for (Thread* slave; (slave = Threads.available_slave(this)) != NULL; )
{
- sp.slavesMask |= 1ULL << slave->idx;
+ sp.slavesMask.set(slave->idx);
slave->activeSplitPoint = &sp;
slave->searching = true; // Slave leaves idle_loop()
slave->notify_one(); // Could be sleeping