]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Retire Application class
[stockfish] / src / search.cpp
index 59c717caa9700e5412b9de78101d791dcd42c6d5..121575f554525c6a2b13b52140a7d4d6fa2f86b6 100644 (file)
@@ -59,6 +59,10 @@ namespace {
   // Used for debugging SMP code.
   const bool FakeSplit = false;
 
+  // Fast lookup table of sliding pieces indexed by Piece
+  const bool Slidings[18] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 };
+  inline bool piece_is_slider(Piece p) { return Slidings[p]; }
+
   // ThreadsManager class is used to handle all the threads related stuff in search,
   // init, starting, parking and, the most important, launching a slave thread at a
   // split point are what this class does. All the access to shared thread data is
@@ -259,6 +263,7 @@ namespace {
   // Multi-threads related variables
   Depth MinimumSplitDepth;
   int MaxThreadsPerSplitPoint;
+  bool UseSleepingMaster;
   ThreadsManager ThreadsMgr;
 
   // Node counters, used only by thread[0] but try to keep in different cache
@@ -451,6 +456,7 @@ bool think(Position& pos, bool infinite, bool ponder, int time[], int increment[
   MaxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
   MultiPV                 = Options["MultiPV"].value<int>();
   UseLogFile              = Options["Use Search Log"].value<bool>();
+  UseSleepingMaster       = Options["Use Sleeping Master"].value<bool>();
 
   if (UseLogFile)
       LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
@@ -1930,7 +1936,7 @@ split_point_start: // At split points actual search starts from here
     int t = current_search_time();
 
     //  Poll for input
-    if (Bioskey())
+    if (data_available())
     {
         // We are line oriented, don't read single chars
         std::string command;
@@ -2178,6 +2184,9 @@ split_point_start: // At split points actual search starts from here
 
     assert(threadID >= 0 && threadID < MAX_THREADS);
 
+    int i;
+    bool allFinished = false;
+
     while (true)
     {
         // Slave threads can exit as soon as AllThreadsShouldExit raises,
@@ -2193,23 +2202,23 @@ split_point_start: // At split points actual search starts from here
         // instead of wasting CPU time polling for work.
         while (   threadID >= ActiveThreads
                || threads[threadID].state == THREAD_INITIALIZING
-               || (!sp && threads[threadID].state == THREAD_AVAILABLE))
+               || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster)))
         {
-            assert(!sp);
-            assert(threadID != 0);
-
-            if (AllThreadsShouldExit)
-                break;
-
             lock_grab(&MPLock);
 
-            // Retest condition under lock protection
-            if (!(   threadID >= ActiveThreads
-                  || threads[threadID].state == THREAD_INITIALIZING
-                  || (!sp && threads[threadID].state == THREAD_AVAILABLE)))
+            // Test with lock held to avoid races with wake_sleeping_thread()
+            for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
+            allFinished = (i == ActiveThreads);
+
+            // Retest sleep conditions under lock protection
+            if (   AllThreadsShouldExit
+                || allFinished
+                || !(   threadID >= ActiveThreads
+                     || threads[threadID].state == THREAD_INITIALIZING
+                     || (threads[threadID].state == THREAD_AVAILABLE && (!sp || UseSleepingMaster))))
             {
                 lock_release(&MPLock);
-                continue;
+                break;
             }
 
             // Put thread to sleep
@@ -2239,14 +2248,19 @@ split_point_start: // At split points actual search starts from here
             assert(threads[threadID].state == THREAD_SEARCHING);
 
             threads[threadID].state = THREAD_AVAILABLE;
+
+            // Wake up master thread so to allow it to return from the idle loop in
+            // case we are the last slave of the split point.
+            if (UseSleepingMaster && threadID != tsp->master && threads[tsp->master].state == THREAD_AVAILABLE)
+                wake_sleeping_thread(tsp->master);
         }
 
         // 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.
-        int i = 0;
-        for ( ; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
+        for (i = 0; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
+        allFinished = (i == ActiveThreads);
 
-        if (i == ActiveThreads)
+        if (allFinished)
         {
             // Because sp->slaves[] is reset under lock protection,
             // be sure sp->lock has been released before to return.
@@ -2310,7 +2324,7 @@ split_point_start: // At split points actual search starts from here
         if (!ok)
         {
             cout << "Failed to create thread number " << i << endl;
-            Application::exit_with_failure();
+            exit(EXIT_FAILURE);
         }
 
         // Wait until the thread has finished launching and is gone to sleep
@@ -2454,6 +2468,7 @@ split_point_start: // At split points actual search starts from here
 
     // Initialize the split point object
     splitPoint.parent = masterThread.splitPoint;
+    splitPoint.master = master;
     splitPoint.stopRequest = false;
     splitPoint.ply = ply;
     splitPoint.depth = depth;