From 588670e8d2ed5735300c5549ef754ceb09f1f461 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Wed, 16 Jan 2013 09:28:41 +0100 Subject: [PATCH 1/1] Big renaming in thread stuff No functional change. Signed-off-by: Marco Costalba --- src/benchmark.cpp | 4 ++-- src/position.h | 2 +- src/search.cpp | 22 ++++++++++----------- src/thread.cpp | 50 +++++++++++++++++++++++------------------------ src/thread.h | 39 +++++++++++++++++++----------------- src/uci.cpp | 4 ++-- 6 files changed, 62 insertions(+), 59 deletions(-) diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 4a383f00..fd45d26e 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -130,8 +130,8 @@ void benchmark(const Position& current, istream& is) { } else { - Threads.start_searching(pos, limits, vector(), st); - Threads.wait_for_search_finished(); + Threads.start_thinking(pos, limits, vector(), st); + Threads.wait_for_think_finished(); nodes += Search::RootPos.nodes_searched(); } } diff --git a/src/position.h b/src/position.h index 7fb840b6..b05d466e 100644 --- a/src/position.h +++ b/src/position.h @@ -30,7 +30,7 @@ /// 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 { diff --git a/src/search.cpp b/src/search.cpp index d86f2493..2b04befa 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1007,7 +1007,7 @@ split_point_start: // At split points actual search starts from here // 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); @@ -1558,7 +1558,7 @@ void Thread::idle_loop() { // 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. @@ -1566,9 +1566,9 @@ void Thread::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; @@ -1588,20 +1588,20 @@ void Thread::idle_loop() { // 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(); @@ -1627,9 +1627,9 @@ void Thread::idle_loop() { 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(); @@ -1640,7 +1640,7 @@ void Thread::idle_loop() { && this != sp->master && !sp->slavesMask) { - assert(!sp->master->is_searching); + assert(!sp->master->searching); sp->master->notify_one(); } diff --git a/src/thread.cpp b/src/thread.cpp index 9bd74989..1336ce07 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -44,7 +44,7 @@ namespace { extern "C" { Thread::Thread() : splitPoints() { - is_searching = do_exit = false; + searching = exit = false; maxPly = splitPointsCnt = 0; curSplitPoint = NULL; idx = Threads.size(); @@ -61,7 +61,7 @@ Thread::Thread() : splitPoints() { 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 } @@ -73,11 +73,11 @@ extern void check_time(); 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(); @@ -97,10 +97,9 @@ void MainThread::idle_loop() { { 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); @@ -108,19 +107,21 @@ void MainThread::idle_loop() { 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() { @@ -162,7 +163,7 @@ bool Thread::cutoff_occurred() const { 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 @@ -283,7 +284,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta, sp.nodes = 0; sp.ss = ss; - assert(master->is_searching); + assert(master->searching); master->curSplitPoint = &sp; int slavesCnt = 0; @@ -299,7 +300,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta, { 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 @@ -321,7 +322,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta, // 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 @@ -330,7 +331,7 @@ Value ThreadPool::split(Position& pos, Stack* ss, Value alpha, Value beta, 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); @@ -347,24 +348,23 @@ template Value ThreadPool::split(Position&, Stack*, Value, Value, Value, template Value ThreadPool::split(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& searchMoves, StateStackPtr& states) { - wait_for_search_finished(); +void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, + const std::vector& searchMoves, StateStackPtr& states) { + wait_for_think_finished(); SearchTime = Time::now(); // As early as possible @@ -380,6 +380,6 @@ void ThreadPool::start_searching(const Position& pos, const LimitsType& limits, 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 } diff --git a/src/thread.h b/src/thread.h index 9d04e5bd..793a3c60 100644 --- a/src/thread.h +++ b/src/thread.h @@ -56,7 +56,7 @@ private: WaitCondition c; }; -class Thread; +struct Thread; struct SplitPoint { @@ -91,9 +91,8 @@ 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(); @@ -114,20 +113,24 @@ public: 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; }; @@ -142,22 +145,25 @@ public: 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(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&, Search::StateStackPtr&); template 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(); @@ -165,10 +171,7 @@ private: TimerThread* timer; Mutex mutex; ConditionVariable sleepCondition; - Depth minimumSplitDepth; int maxThreadsPerSplitPoint; -public: - bool sleepWhileIdle; }; extern ThreadPool Threads; diff --git a/src/uci.cpp b/src/uci.cpp index ad7a8d13..5721e93f 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -113,7 +113,7 @@ void UCI::loop(const string& args) { } 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 } @@ -207,6 +207,6 @@ namespace { else if (token == "ponder") limits.ponder = true; } - Threads.start_searching(pos, limits, searchMoves, SetupStates); + Threads.start_thinking(pos, limits, searchMoves, SetupStates); } } -- 2.39.2