From 750dfa0521472e86c67f870fe7ca413d670cafe2 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 6 Aug 2017 04:43:02 -0700 Subject: [PATCH] Fix some races and clarify the code Better split code that should be run at startup from code run at ucinewgame. Also fix several races when 'bench', 'perft' and 'ucinewgame' are sent just after 'bestomve' from the engine threads are still running. Also use a specific UI thread instead of main thread when setting up the Position object used by UI uci loop. This fixes a race when sending 'eval' command while searching. We accept a race on 'setoption' to allow the GUI to change an option while engine is searching withouth stalling the pipe. Note that changing an option while searchingg is anyhow not mandated by UCI protocol. No functional change. --- src/benchmark.cpp | 4 ++-- src/main.cpp | 4 ++++ src/search.cpp | 5 ++++- src/uci.cpp | 17 ++++------------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 21c6ec11..f61b5da3 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -109,9 +109,9 @@ void benchmark(const Position& current, istream& is) { string fenFile = (is >> token) ? token : "default"; string limitType = (is >> token) ? token : "depth"; - Options["Hash"] = ttSize; + Search::clear(); // Wait for search finished Options["Threads"] = threads; - Search::clear(); + Options["Hash"] = ttSize; if (limitType == "time") limits.movetime = stoi(limit); // movetime is in millisecs diff --git a/src/main.cpp b/src/main.cpp index 063ce76e..75cdfc83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,6 +24,7 @@ #include "position.h" #include "search.h" #include "thread.h" +#include "tt.h" #include "uci.h" #include "syzygy/tbprobe.h" @@ -42,7 +43,10 @@ int main(int argc, char* argv[]) { Bitbases::init(); Search::init(); Pawns::init(); + Tablebases::init(Options["SyzygyPath"]); + TT.resize(Options["Hash"]); Threads.init(); + Search::clear(); // After threads are up UCI::loop(argc, argv); diff --git a/src/search.cpp b/src/search.cpp index 673d3a23..11dcdb34 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -183,10 +183,13 @@ void Search::init() { } -/// Search::clear() resets search state to its initial value, to obtain reproducible results +/// Search::clear() resets search state to its initial value void Search::clear() { + Threads.main()->wait_for_search_finished(); + + Time.availableNodes = 0; TT.clear(); for (Thread* th : Threads) diff --git a/src/uci.cpp b/src/uci.cpp index afc775c1..8f6416bd 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -138,15 +138,6 @@ namespace { Threads.start_thinking(pos, States, limits); } - // On ucinewgame following steps are needed to reset the state - void newgame() { - - TT.resize(Options["Hash"]); - Search::clear(); - Tablebases::init(Options["SyzygyPath"]); - Time.availableNodes = 0; - } - } // namespace @@ -160,10 +151,9 @@ void UCI::loop(int argc, char* argv[]) { Position pos; string token, cmd; + Thread* uiThread = new Thread(); - newgame(); // Implied ucinewgame before the first position command - - pos.set(StartFEN, false, &States->back(), Threads.main()); + pos.set(StartFEN, false, &States->back(), uiThread); for (int i = 1; i < argc; ++i) cmd += std::string(argv[i]) + " "; @@ -197,7 +187,7 @@ void UCI::loop(int argc, char* argv[]) { << "\n" << Options << "\nuciok" << sync_endl; - else if (token == "ucinewgame") newgame(); + else if (token == "ucinewgame") Search::clear(); else if (token == "isready") sync_cout << "readyok" << sync_endl; else if (token == "go") go(pos, is); else if (token == "position") position(pos, is); @@ -225,6 +215,7 @@ void UCI::loop(int argc, char* argv[]) { } while (token != "quit" && argc == 1); // Passed args have one-shot behaviour Threads.main()->wait_for_search_finished(); + delete uiThread; } -- 2.39.2