namespace {
+ // start_routine() is the C function which is called when a new thread
+ // is launched. It is a wrapper to the virtual function idle_loop().
+
+ extern "C" { long start_routine(ThreadBase* th) { th->idle_loop(); return 0; } }
+
+
// Helpers to launch a thread after creation and joining before delete. Must be
// outside Thread c'tor and d'tor because the object must be fully initialized
// when start_routine (and hence virtual idle_loop) is called and when joining.
template<typename T> T* new_thread() {
T* th = new T();
- th->nativeThread = std::thread(&ThreadBase::idle_loop, th); // Will go to sleep
+ thread_create(th->handle, start_routine, th); // Will go to sleep
return th;
}
th->mutex.unlock();
th->notify_one();
- th->nativeThread.join(); // Wait for thread termination
+ thread_join(th->handle); // Wait for thread termination
delete th;
}
void ThreadBase::notify_one() {
- std::unique_lock<std::mutex>(this->mutex);
+ mutex.lock();
sleepCondition.notify_one();
+ mutex.unlock();
}
void ThreadBase::wait_for(volatile const bool& condition) {
- std::unique_lock<std::mutex> lk(mutex);
- sleepCondition.wait(lk, [&]{ return condition; });
+ mutex.lock();
+ while (!condition) sleepCondition.wait(mutex);
+ mutex.unlock();
}
Thread::Thread() /* : splitPoints() */ { // Initialization of non POD broken in MSVC
searching = false;
- maxPly = splitPointsSize = 0;
- activeSplitPoint = nullptr;
- activePosition = nullptr;
+ maxPly = 0;
+ splitPointsSize = 0;
+ activeSplitPoint = NULL;
+ activePosition = NULL;
idx = Threads.size(); // Starts from 0
}
// Make a local copy to be sure it doesn't become zero under our feet while
// testing next condition and so leading to an out of bounds access.
- const int size = splitPointsSize;
+ const size_t size = splitPointsSize;
// No split points means that the thread is available as a slave for any
// other thread otherwise apply the "helpful master" concept if possible.
// Pick and init the next available split point
SplitPoint& sp = splitPoints[splitPointsSize];
- sp.masterThread = this;
+ sp.master = this;
sp.parentSplitPoint = activeSplitPoint;
sp.slavesMask = 0, sp.slavesMask.set(idx);
sp.depth = depth;
sp.allSlavesSearching = true; // Must be set under lock protection
++splitPointsSize;
activeSplitPoint = &sp;
- activePosition = nullptr;
+ activePosition = NULL;
Thread* slave;
- while ((slave = Threads.available_slave(this)) != nullptr)
+ while ( sp.slavesMask.count() < MAX_SLAVES_PER_SPLITPOINT
+ && (slave = Threads.available_slave(this)) != NULL)
{
sp.slavesMask.set(slave->idx);
slave->activeSplitPoint = &sp;
while (!exit)
{
- std::unique_lock<std::mutex> lk(mutex);
+ mutex.lock();
if (!exit)
- sleepCondition.wait_for(lk, std::chrono::milliseconds(run ? Resolution : INT_MAX));
+ sleepCondition.wait_for(mutex, run ? Resolution : INT_MAX);
- lk.unlock();
+ mutex.unlock();
if (run)
check_time();
while (!exit)
{
- std::unique_lock<std::mutex> lk(mutex);
+ mutex.lock();
thinking = false;
while (!thinking && !exit)
{
Threads.sleepCondition.notify_one(); // Wake up the UI thread if needed
- sleepCondition.wait(lk);
+ sleepCondition.wait(mutex);
}
- lk.unlock();
+ mutex.unlock();
if (!exit)
{
delete_thread(timer); // As first because check_time() accesses threads data
- for (Thread* th : *this)
- delete_thread(th);
+ for (iterator it = begin(); it != end(); ++it)
+ delete_thread(*it);
}
Thread* ThreadPool::available_slave(const Thread* master) const {
- for (Thread* th : *this)
- if (th->available_to(master))
- return th;
+ for (const_iterator it = begin(); it != end(); ++it)
+ if ((*it)->available_to(master))
+ return *it;
- return nullptr;
+ return NULL;
}
void ThreadPool::wait_for_think_finished() {
- std::unique_lock<std::mutex> lk(main()->mutex);
- sleepCondition.wait(lk, [&]{ return !main()->thinking; });
+ MainThread* th = main();
+ th->mutex.lock();
+ while (th->thinking) sleepCondition.wait(th->mutex);
+ th->mutex.unlock();
}
Limits = limits;
if (states.get()) // If we don't set a new position, preserve current state
{
- SetupStates = std::move(states); // Ownership transfer here
+ SetupStates = states; // Ownership transfer here
assert(!states.get());
}
- for (const auto& m : MoveList<LEGAL>(pos))
+ for (MoveList<LEGAL> it(pos); *it; ++it)
if ( limits.searchmoves.empty()
- || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
- RootMoves.push_back(RootMove(m));
+ || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), *it))
+ RootMoves.push_back(RootMove(*it));
main()->thinking = true;
main()->notify_one(); // Starts main thread