No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
}
else
{
- Threads.start_searching(pos, limits, vector<Move>(), st);
- Threads.wait_for_search_finished();
+ Threads.start_thinking(pos, limits, vector<Move>(), st);
+ Threads.wait_for_think_finished();
nodes += Search::RootPos.nodes_searched();
}
}
/// The checkInfo struct is initialized at c'tor time and keeps info used
/// to detect if a move gives check.
class Position;
-class Thread;
+struct Thread;
struct CheckInfo {
// Step 19. Check for splitting the search
if ( !SpNode
- && depth >= Threads.min_split_depth()
+ && depth >= Threads.minimumSplitDepth
&& Threads.available_slave_exists(thisThread))
{
assert(bestValue < beta);
// object for which the thread is the master.
const SplitPoint* sp_master = splitPointsCnt ? curSplitPoint : NULL;
- assert(!sp_master || (sp_master->master == this && is_searching));
+ assert(!sp_master || (sp_master->master == this && searching));
// 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 we are not searching, wait for a condition to be signaled
// instead of wasting CPU time polling for work.
- while (do_exit || (!is_searching && Threads.sleepWhileIdle))
+ while ((!searching && Threads.sleepWhileIdle) || exit)
{
- if (do_exit)
+ if (exit)
{
assert(!sp_master);
return;
// particular we need to avoid a deadlock in case a master thread has,
// in the meanwhile, allocated us and sent the wake_up() call before we
// had the chance to grab the lock.
- if (!is_searching && !do_exit)
+ if (!searching && !exit)
sleepCondition.wait(mutex);
mutex.unlock();
}
// If this thread has been assigned work, launch a search
- if (is_searching)
+ if (searching)
{
- assert(!do_exit);
+ assert(!exit);
Threads.mutex.lock();
- assert(is_searching);
+ assert(searching);
SplitPoint* sp = curSplitPoint;
Threads.mutex.unlock();
else
assert(false);
- assert(is_searching);
+ assert(searching);
- is_searching = false;
+ searching = false;
sp->activePositions[idx] = NULL;
sp->slavesMask &= ~(1ULL << idx);
sp->nodes += pos.nodes_searched();
&& this != sp->master
&& !sp->slavesMask)
{
- assert(!sp->master->is_searching);
+ assert(!sp->master->searching);
sp->master->notify_one();
}
Thread::Thread() : splitPoints() {
- is_searching = do_exit = false;
+ searching = exit = false;
maxPly = splitPointsCnt = 0;
curSplitPoint = NULL;
idx = Threads.size();
Thread::~Thread() {
- do_exit = true; // Search must be already finished
+ exit = true; // Search must be already finished
notify_one();
thread_join(handle); // Wait for thread termination
}
void TimerThread::idle_loop() {
- while (!do_exit)
+ while (!exit)
{
mutex.lock();
- if (!do_exit)
+ if (!exit)
sleepCondition.wait_for(mutex, msec ? msec : INT_MAX);
mutex.unlock();
{
mutex.lock();
- is_finished = true; // Always return to sleep after a search
- is_searching = false;
+ thinking = false;
- while (is_finished && !do_exit)
+ while (!thinking && !exit)
{
Threads.sleepCondition.notify_one(); // Wake up UI thread if needed
sleepCondition.wait(mutex);
mutex.unlock();
- if (do_exit)
+ if (exit)
return;
- is_searching = true;
+ searching = true;
Search::think();
- assert(is_searching);
+ assert(searching);
+
+ searching = false;
}
}
-// Thread::notify_one() wakes up the thread, normally at split time
+// Thread::notify_one() wakes up the thread when there is some search to do
void Thread::notify_one() {
bool Thread::is_available_to(Thread* master) const {
- if (is_searching)
+ if (searching)
return false;
// Make a local copy to be sure doesn't become zero under our feet while
sp.nodes = 0;
sp.ss = ss;
- assert(master->is_searching);
+ assert(master->searching);
master->curSplitPoint = &sp;
int slavesCnt = 0;
{
sp.slavesMask |= 1ULL << i;
threads[i]->curSplitPoint = &sp;
- threads[i]->is_searching = true; // Slave leaves idle_loop()
+ threads[i]->searching = true; // Slave leaves idle_loop()
threads[i]->notify_one(); // Could be sleeping
if (++slavesCnt + 1 >= maxThreadsPerSplitPoint) // Master is always included
// In helpful master concept a master can help only a sub-tree of its split
// point, and because here is all finished is not possible master is booked.
- assert(!master->is_searching);
+ assert(!master->searching);
}
// We have returned from the idle loop, which means that all threads are
mutex.lock();
sp.mutex.lock();
- master->is_searching = true;
+ master->searching = true;
master->splitPointsCnt--;
master->curSplitPoint = sp.parent;
pos.set_nodes_searched(pos.nodes_searched() + sp.nodes);
template Value ThreadPool::split<true>(Position&, Stack*, Value, Value, Value, Move*, Depth, Move, int, MovePicker&, int);
-// wait_for_search_finished() waits for main thread to go to sleep, this means
-// search is finished. Then returns.
+// wait_for_think_finished() waits for main thread to go to sleep then returns
-void ThreadPool::wait_for_search_finished() {
+void ThreadPool::wait_for_think_finished() {
MainThread* t = main_thread();
t->mutex.lock();
- while (!t->is_finished) sleepCondition.wait(t->mutex);
+ while (t->thinking) sleepCondition.wait(t->mutex);
t->mutex.unlock();
}
-// start_searching() wakes up the main thread sleeping in main_loop() so to start
+// start_thinking() wakes up the main thread sleeping in main_loop() so to start
// a new search, then returns immediately.
-void ThreadPool::start_searching(const Position& pos, const LimitsType& limits,
- const std::vector<Move>& searchMoves, StateStackPtr& states) {
- wait_for_search_finished();
+void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
+ const std::vector<Move>& searchMoves, StateStackPtr& states) {
+ wait_for_think_finished();
SearchTime = Time::now(); // As early as possible
if (searchMoves.empty() || count(searchMoves.begin(), searchMoves.end(), ml.move()))
RootMoves.push_back(RootMove(ml.move()));
- main_thread()->is_finished = false;
+ main_thread()->thinking = true;
main_thread()->notify_one(); // Starts main thread
}
WaitCondition c;
};
-class Thread;
+struct Thread;
struct SplitPoint {
/// tables so that once we get a pointer to an entry its life time is unlimited
/// and we don't have to care about someone changing the entry under our feet.
-class Thread {
+struct Thread {
-public:
Thread();
virtual ~Thread();
NativeHandle handle;
SplitPoint* volatile curSplitPoint;
volatile int splitPointsCnt;
- volatile bool is_searching;
- volatile bool do_exit;
+ volatile bool searching;
+ volatile bool exit;
};
-struct TimerThread : public Thread {
- TimerThread() : msec(0) {}
+
+/// MainThread and TimerThread are sublassed from Thread to charaterize the two
+/// special threads: the main one and the recurring timer.
+
+struct MainThread : public Thread {
+ MainThread() : thinking(true) {} // Avoid a race with start_thinking()
virtual void idle_loop();
- int msec;
+ volatile bool thinking;
};
-struct MainThread : public Thread {
- MainThread() : is_finished(false) {} // Avoid a race with start_searching()
+struct TimerThread : public Thread {
+ TimerThread() : msec(0) {}
virtual void idle_loop();
- volatile bool is_finished;
+ int msec;
};
void exit(); // be initialized and valid during the whole thread lifetime.
Thread& operator[](size_t id) { return *threads[id]; }
- int min_split_depth() const { return minimumSplitDepth; }
size_t size() const { return threads.size(); }
MainThread* main_thread() { return static_cast<MainThread*>(threads[0]); }
TimerThread* timer_thread() { return timer; }
void read_uci_options();
bool available_slave_exists(Thread* master) const;
- void wait_for_search_finished();
- void start_searching(const Position&, const Search::LimitsType&,
+ void wait_for_think_finished();
+ void start_thinking(const Position&, const Search::LimitsType&,
const std::vector<Move>&, Search::StateStackPtr&);
template <bool Fake>
Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove,
Depth depth, Move threatMove, int moveCount, MovePicker& mp, int nodeType);
+
+ bool sleepWhileIdle;
+ Depth minimumSplitDepth;
+
private:
- friend class Thread;
+ friend struct Thread;
friend struct MainThread;
friend void check_time();
TimerThread* timer;
Mutex mutex;
ConditionVariable sleepCondition;
- Depth minimumSplitDepth;
int maxThreadsPerSplitPoint;
-public:
- bool sleepWhileIdle;
};
extern ThreadPool Threads;
} while (token != "quit" && args.empty()); // Args have one-shot behaviour
- Threads.wait_for_search_finished(); // Cannot quit while search is running
+ Threads.wait_for_think_finished(); // Cannot quit while search is running
}
else if (token == "ponder") limits.ponder = true;
}
- Threads.start_searching(pos, limits, searchMoves, SetupStates);
+ Threads.start_thinking(pos, limits, searchMoves, SetupStates);
}
}