Fix some races and clarify the code
authorMarco Costalba <mcostalba@gmail.com>
Sun, 6 Aug 2017 11:43:02 +0000 (04:43 -0700)
committerMarco Costalba <mcostalba@gmail.com>
Thu, 10 Aug 2017 17:19:56 +0000 (10:19 -0700)
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
src/main.cpp
src/search.cpp
src/uci.cpp

index 21c6ec1123fb43fe4a648d0ccc411e4842d8ed7c..f61b5da31bef9783f39a9830ce72f7612b1686c1 100644 (file)
@@ -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
index 063ce76e3503d8b6e27107444c7548fb69e8ce84..75cdfc837c94d084b6bbb5e00a21b754168bba03 100644 (file)
@@ -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);
 
index 673d3a230ec5257809eeab33576e9611d62489cf..11dcdb34f13840a1b8ff43a7b08df4273fe972f9 100644 (file)
@@ -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)
index afc775c1f60173b20c1bde05890ad45207504688..8f6416bdcb7b866b984e53b5ac6be64c4a7e47b8 100644 (file)
@@ -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;
 }