]> git.sesse.net Git - stockfish/commitdiff
Large API rename in ThreadsManager
authorMarco Costalba <mcostalba@gmail.com>
Sun, 24 Apr 2011 23:22:48 +0000 (00:22 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 25 Apr 2011 09:30:39 +0000 (10:30 +0100)
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/evaluate.cpp
src/main.cpp
src/position.cpp
src/search.cpp
src/thread.cpp
src/thread.h

index e75251f472a8b532e91226b78a76ea3f8cc2fd19..649842dc87384f568b390e497649f5c62fba6195 100644 (file)
@@ -303,7 +303,7 @@ Value do_evaluate(const Position& pos, Value& margin) {
   margins[WHITE] = margins[BLACK] = VALUE_ZERO;
 
   // Probe the material hash table
   margins[WHITE] = margins[BLACK] = VALUE_ZERO;
 
   // Probe the material hash table
-  MaterialInfo* mi = ThreadsMgr[pos.thread()].materialTable.get_material_info(pos);
+  MaterialInfo* mi = Threads[pos.thread()].materialTable.get_material_info(pos);
   bonus += mi->material_value();
 
   // If we have a specialized evaluation function for the current material
   bonus += mi->material_value();
 
   // If we have a specialized evaluation function for the current material
@@ -315,7 +315,7 @@ Value do_evaluate(const Position& pos, Value& margin) {
   }
 
   // Probe the pawn hash table
   }
 
   // Probe the pawn hash table
-  ei.pi = ThreadsMgr[pos.thread()].pawnTable.get_pawn_info(pos);
+  ei.pi = Threads[pos.thread()].pawnTable.get_pawn_info(pos);
   bonus += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
 
   // Initialize attack and king safety bitboards
   bonus += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
 
   // Initialize attack and king safety bitboards
index 0e1690440dc1e498febec0d769519af4406a37c9..efc746b38b483b859e015a00dfac259b2a22d931 100644 (file)
@@ -55,7 +55,7 @@ int main(int argc, char* argv[]) {
   Position::init_piece_square_tables();
   init_kpk_bitbase();
   init_search();
   Position::init_piece_square_tables();
   init_kpk_bitbase();
   init_search();
-  ThreadsMgr.init_threads();
+  Threads.init();
 
 #ifdef USE_CALLGRIND
   CALLGRIND_START_INSTRUMENTATION;
 
 #ifdef USE_CALLGRIND
   CALLGRIND_START_INSTRUMENTATION;
@@ -82,6 +82,6 @@ int main(int argc, char* argv[]) {
            << "[limit = 12] [fen positions file = default] "
            << "[depth, time, perft or node limited = depth]" << endl;
 
            << "[limit = 12] [fen positions file = default] "
            << "[depth, time, perft or node limited = depth]" << endl;
 
-  ThreadsMgr.exit_threads();
+  Threads.exit();
   return 0;
 }
   return 0;
 }
index 2172180cfb694783feddebd048e7546133475f98..657a4d581e13337985aad7ecef434c95eb286c57 100644 (file)
@@ -1048,8 +1048,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   }
 
   // Prefetch pawn and material hash tables
   }
 
   // Prefetch pawn and material hash tables
-  ThreadsMgr[threadID].pawnTable.prefetch(st->pawnKey);
-  ThreadsMgr[threadID].materialTable.prefetch(st->materialKey);
+  Threads[threadID].pawnTable.prefetch(st->pawnKey);
+  Threads[threadID].materialTable.prefetch(st->materialKey);
 
   // Update incremental scores
   st->value += pst_delta(piece, from, to);
 
   // Update incremental scores
   st->value += pst_delta(piece, from, to);
index 751049cd4557a82f789aa367cbe601c771f01353..3e36948feacac2c30cd4a31b2317f19125bcb074 100644 (file)
@@ -436,10 +436,10 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
   SkillLevel = Options["Skill level"].value<int>();
 
   read_evaluation_uci_options(pos.side_to_move());
   SkillLevel = Options["Skill level"].value<int>();
 
   read_evaluation_uci_options(pos.side_to_move());
-  ThreadsMgr.read_uci_options();
+  Threads.read_uci_options();
 
   // If needed allocate pawn and material hash tables and adjust TT size
 
   // If needed allocate pawn and material hash tables and adjust TT size
-  ThreadsMgr.init_hash_tables();
+  Threads.init_hash_tables();
   TT.set_size(Options["Hash"].value<int>());
 
   if (Options["Clear Hash"].value<bool>())
   TT.set_size(Options["Hash"].value<int>());
 
   if (Options["Clear Hash"].value<bool>())
@@ -454,10 +454,10 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
   MultiPV = (SkillLevelEnabled ? Max(UCIMultiPV, 4) : UCIMultiPV);
 
   // Wake up needed threads and reset maxPly counter
   MultiPV = (SkillLevelEnabled ? Max(UCIMultiPV, 4) : UCIMultiPV);
 
   // Wake up needed threads and reset maxPly counter
-  for (int i = 0; i < ThreadsMgr.active_threads(); i++)
+  for (int i = 0; i < Threads.size(); i++)
   {
   {
-      ThreadsMgr[i].wake_up();
-      ThreadsMgr[i].maxPly = 0;
+      Threads[i].wake_up();
+      Threads[i].maxPly = 0;
   }
 
   // Write to log file and keep it open to be accessed during the search
   }
 
   // Write to log file and keep it open to be accessed during the search
@@ -499,7 +499,7 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
   }
 
   // This makes all the threads to go to sleep
   }
 
   // This makes all the threads to go to sleep
-  ThreadsMgr.set_active_threads(1);
+  Threads.set_size(1);
 
   // If we are pondering or in infinite search, we shouldn't print the
   // best move before we are told to do so.
 
   // If we are pondering or in infinite search, we shouldn't print the
   // best move before we are told to do so.
@@ -625,9 +625,9 @@ namespace {
 
         // Retrieve max searched depth among threads
         selDepth = 0;
 
         // Retrieve max searched depth among threads
         selDepth = 0;
-        for (int i = 0; i < ThreadsMgr.active_threads(); i++)
-            if (ThreadsMgr[i].maxPly > selDepth)
-                selDepth = ThreadsMgr[i].maxPly;
+        for (int i = 0; i < Threads.size(); i++)
+            if (Threads[i].maxPly > selDepth)
+                selDepth = Threads[i].maxPly;
 
         // Send PV line to GUI and to log file
         for (int i = 0; i < Min(UCIMultiPV, (int)Rml.size()); i++)
 
         // Send PV line to GUI and to log file
         for (int i = 0; i < Min(UCIMultiPV, (int)Rml.size()); i++)
@@ -708,7 +708,7 @@ namespace {
     assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
     assert(beta > alpha && beta <= VALUE_INFINITE);
     assert(PvNode || alpha == beta - 1);
     assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
     assert(beta > alpha && beta <= VALUE_INFINITE);
     assert(PvNode || alpha == beta - 1);
-    assert(pos.thread() >= 0 && pos.thread() < ThreadsMgr.active_threads());
+    assert(pos.thread() >= 0 && pos.thread() < Threads.size());
 
     Move movesSearched[MAX_MOVES];
     int64_t nodes;
 
     Move movesSearched[MAX_MOVES];
     int64_t nodes;
@@ -731,8 +731,8 @@ namespace {
     ss->ply = (ss-1)->ply + 1;
 
     // Used to send selDepth info to GUI
     ss->ply = (ss-1)->ply + 1;
 
     // Used to send selDepth info to GUI
-    if (PvNode && ThreadsMgr[threadID].maxPly < ss->ply)
-        ThreadsMgr[threadID].maxPly = ss->ply;
+    if (PvNode && Threads[threadID].maxPly < ss->ply)
+        Threads[threadID].maxPly = ss->ply;
 
     if (SpNode)
     {
 
     if (SpNode)
     {
@@ -758,7 +758,7 @@ namespace {
 
     // Step 2. Check for aborted search and immediate draw
     if ((   StopRequest
 
     // Step 2. Check for aborted search and immediate draw
     if ((   StopRequest
-         || ThreadsMgr.cutoff_at_splitpoint(threadID)
+         || Threads[threadID].cutoff_occurred()
          || pos.is_draw()
          || ss->ply > PLY_MAX) && !Root)
         return VALUE_DRAW;
          || pos.is_draw()
          || ss->ply > PLY_MAX) && !Root)
         return VALUE_DRAW;
@@ -939,7 +939,7 @@ split_point_start: // At split points actual search starts from here
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
            && (move = mp.get_next_move()) != MOVE_NONE
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
            && (move = mp.get_next_move()) != MOVE_NONE
-           && !ThreadsMgr.cutoff_at_splitpoint(threadID))
+           && !Threads[threadID].cutoff_occurred())
     {
       assert(move_is_ok(move));
 
     {
       assert(move_is_ok(move));
 
@@ -1154,7 +1154,7 @@ split_point_start: // At split points actual search starts from here
           alpha = sp->alpha;
       }
 
           alpha = sp->alpha;
       }
 
-      if (value > bestValue && !(SpNode && ThreadsMgr.cutoff_at_splitpoint(threadID)))
+      if (value > bestValue && !(SpNode && Threads[threadID].cutoff_occurred()))
       {
           bestValue = value;
 
       {
           bestValue = value;
 
@@ -1171,7 +1171,7 @@ split_point_start: // At split points actual search starts from here
                       sp->alpha = value;
               }
               else if (SpNode)
                       sp->alpha = value;
               }
               else if (SpNode)
-                  sp->betaCutoff = true;
+                  sp->is_betaCutoff = true;
 
               if (value == value_mate_in(ss->ply + 1))
                   ss->mateKiller = move;
 
               if (value == value_mate_in(ss->ply + 1))
                   ss->mateKiller = move;
@@ -1227,14 +1227,13 @@ split_point_start: // At split points actual search starts from here
       // Step 18. Check for split
       if (   !Root
           && !SpNode
       // Step 18. Check for split
       if (   !Root
           && !SpNode
-          && depth >= ThreadsMgr.min_split_depth()
-          && ThreadsMgr.active_threads() > 1
+          && depth >= Threads.min_split_depth()
           && bestValue < beta
           && bestValue < beta
-          && ThreadsMgr.available_thread_exists(threadID)
+          && Threads.available_slave_exists(threadID)
           && !StopRequest
           && !StopRequest
-          && !ThreadsMgr.cutoff_at_splitpoint(threadID))
-          ThreadsMgr.split<FakeSplit>(pos, ss, &alpha, beta, &bestValue, depth,
-                                      threatMove, moveCount, &mp, PvNode);
+          && !Threads[threadID].cutoff_occurred())
+          Threads.split<FakeSplit>(pos, ss, &alpha, beta, &bestValue, depth,
+                                   threatMove, moveCount, &mp, PvNode);
     }
 
     // Step 19. Check for mate and stalemate
     }
 
     // Step 19. Check for mate and stalemate
@@ -1247,7 +1246,7 @@ split_point_start: // At split points actual search starts from here
     // Step 20. Update tables
     // If the search is not aborted, update the transposition table,
     // history counters, and killer moves.
     // Step 20. Update tables
     // If the search is not aborted, update the transposition table,
     // history counters, and killer moves.
-    if (!SpNode && !StopRequest && !ThreadsMgr.cutoff_at_splitpoint(threadID))
+    if (!SpNode && !StopRequest && !Threads[threadID].cutoff_occurred())
     {
         move = bestValue <= oldAlpha ? MOVE_NONE : ss->bestMove;
         vt   = bestValue <= oldAlpha ? VALUE_TYPE_UPPER
     {
         move = bestValue <= oldAlpha ? MOVE_NONE : ss->bestMove;
         vt   = bestValue <= oldAlpha ? VALUE_TYPE_UPPER
@@ -1271,7 +1270,7 @@ split_point_start: // At split points actual search starts from here
     if (SpNode)
     {
         // Here we have the lock still grabbed
     if (SpNode)
     {
         // Here we have the lock still grabbed
-        sp->slaves[threadID] = 0;
+        sp->is_slave[threadID] = false;
         sp->nodes += pos.nodes_searched();
         lock_release(&(sp->lock));
     }
         sp->nodes += pos.nodes_searched();
         lock_release(&(sp->lock));
     }
@@ -1292,7 +1291,7 @@ split_point_start: // At split points actual search starts from here
     assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
     assert(PvNode || alpha == beta - 1);
     assert(depth <= 0);
     assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
     assert(PvNode || alpha == beta - 1);
     assert(depth <= 0);
-    assert(pos.thread() >= 0 && pos.thread() < ThreadsMgr.active_threads());
+    assert(pos.thread() >= 0 && pos.thread() < Threads.size());
 
     StateInfo st;
     Move ttMove, move;
 
     StateInfo st;
     Move ttMove, move;
@@ -2112,27 +2111,27 @@ void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
       if (allThreadsShouldExit)
       {
           assert(!sp);
       if (allThreadsShouldExit)
       {
           assert(!sp);
-          threads[threadID].state = THREAD_TERMINATED;
+          threads[threadID].state = Thread::TERMINATED;
           return;
       }
 
       // If we are not thinking, wait for a condition to be signaled
       // instead of wasting CPU time polling for work.
       while (   threadID >= activeThreads
           return;
       }
 
       // If we are not thinking, wait for a condition to be signaled
       // instead of wasting CPU time polling for work.
       while (   threadID >= activeThreads
-             || threads[threadID].state == THREAD_INITIALIZING
-             || (useSleepingThreads && threads[threadID].state == THREAD_AVAILABLE))
+             || threads[threadID].state == Thread::INITIALIZING
+             || (useSleepingThreads && threads[threadID].state == Thread::AVAILABLE))
       {
           assert(!sp || useSleepingThreads);
           assert(threadID != 0 || useSleepingThreads);
 
       {
           assert(!sp || useSleepingThreads);
           assert(threadID != 0 || useSleepingThreads);
 
-          if (threads[threadID].state == THREAD_INITIALIZING)
-              threads[threadID].state = THREAD_AVAILABLE;
+          if (threads[threadID].state == Thread::INITIALIZING)
+              threads[threadID].state = Thread::AVAILABLE;
 
           // Grab the lock to avoid races with Thread::wake_up()
           lock_grab(&threads[threadID].sleepLock);
 
           // If we are master and all slaves have finished do not go to sleep
 
           // Grab the lock to avoid races with Thread::wake_up()
           lock_grab(&threads[threadID].sleepLock);
 
           // If we are master and all slaves have finished do not go to sleep
-          for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {}
+          for (i = 0; sp && i < activeThreads && !sp->is_slave[i]; i++) {}
           allFinished = (i == activeThreads);
 
           if (allFinished || allThreadsShouldExit)
           allFinished = (i == activeThreads);
 
           if (allFinished || allThreadsShouldExit)
@@ -2142,18 +2141,18 @@ void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
           }
 
           // Do sleep here after retesting sleep conditions
           }
 
           // Do sleep here after retesting sleep conditions
-          if (threadID >= activeThreads || threads[threadID].state == THREAD_AVAILABLE)
+          if (threadID >= activeThreads || threads[threadID].state == Thread::AVAILABLE)
               cond_wait(&threads[threadID].sleepCond, &threads[threadID].sleepLock);
 
           lock_release(&threads[threadID].sleepLock);
       }
 
       // If this thread has been assigned work, launch a search
               cond_wait(&threads[threadID].sleepCond, &threads[threadID].sleepLock);
 
           lock_release(&threads[threadID].sleepLock);
       }
 
       // If this thread has been assigned work, launch a search
-      if (threads[threadID].state == THREAD_WORKISWAITING)
+      if (threads[threadID].state == Thread::WORKISWAITING)
       {
           assert(!allThreadsShouldExit);
 
       {
           assert(!allThreadsShouldExit);
 
-          threads[threadID].state = THREAD_SEARCHING;
+          threads[threadID].state = Thread::SEARCHING;
 
           // Copy split point position and search stack and call search()
           // with SplitPoint template parameter set to true.
 
           // Copy split point position and search stack and call search()
           // with SplitPoint template parameter set to true.
@@ -2169,21 +2168,21 @@ void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
           else
               search<NonPV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
 
           else
               search<NonPV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
 
-          assert(threads[threadID].state == THREAD_SEARCHING);
+          assert(threads[threadID].state == Thread::SEARCHING);
 
 
-          threads[threadID].state = THREAD_AVAILABLE;
+          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 (   useSleepingThreads
               && threadID != tsp->master
 
           // 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 (   useSleepingThreads
               && threadID != tsp->master
-              && threads[tsp->master].state == THREAD_AVAILABLE)
+              && threads[tsp->master].state == Thread::AVAILABLE)
               threads[tsp->master].wake_up();
       }
 
       // 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.
               threads[tsp->master].wake_up();
       }
 
       // 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.
-      for (i = 0; sp && i < activeThreads && !sp->slaves[i]; i++) {}
+      for (i = 0; sp && i < activeThreads && !sp->is_slave[i]; i++) {}
       allFinished = (i == activeThreads);
 
       if (allFinished)
       allFinished = (i == activeThreads);
 
       if (allFinished)
@@ -2195,9 +2194,9 @@ void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
 
           // In helpful master concept a master can help only a sub-tree, and
           // because here is all finished is not possible master is booked.
 
           // In helpful master concept a master can help only a sub-tree, and
           // because here is all finished is not possible master is booked.
-          assert(threads[threadID].state == THREAD_AVAILABLE);
+          assert(threads[threadID].state == Thread::AVAILABLE);
 
 
-          threads[threadID].state = THREAD_SEARCHING;
+          threads[threadID].state = Thread::SEARCHING;
           return;
       }
   }
           return;
       }
   }
index 002819de566ce71a2c91e2566ca481bf1376445c..dee37d0dd740b7f6bb784c8cdf8eb0115282ff91 100644 (file)
@@ -22,7 +22,7 @@
 #include "thread.h"
 #include "ucioption.h"
 
 #include "thread.h"
 #include "ucioption.h"
 
-ThreadsManager ThreadsMgr; // Global object definition
+ThreadsManager Threads; // Global object definition
 
 namespace {
 
 
 namespace {
 
@@ -35,7 +35,7 @@ namespace {
 
   void* init_thread(void* threadID) {
 
 
   void* init_thread(void* threadID) {
 
-    ThreadsMgr.idle_loop(*(int*)threadID, NULL);
+    Threads.idle_loop(*(int*)threadID, NULL);
     return NULL;
   }
 
     return NULL;
   }
 
@@ -43,7 +43,7 @@ namespace {
 
   DWORD WINAPI init_thread(LPVOID threadID) {
 
 
   DWORD WINAPI init_thread(LPVOID threadID) {
 
-    ThreadsMgr.idle_loop(*(int*)threadID, NULL);
+    Threads.idle_loop(*(int*)threadID, NULL);
     return 0;
   }
 
     return 0;
   }
 
@@ -52,6 +52,56 @@ namespace {
 }
 
 
 }
 
 
+// wake_up() wakes up the thread, normally at the beginning of the search or,
+// if "sleeping threads" is used, when there is some work to do.
+
+void Thread::wake_up() {
+
+  lock_grab(&sleepLock);
+  cond_signal(&sleepCond);
+  lock_release(&sleepLock);
+}
+
+
+// cutoff_occurred() checks whether a beta cutoff has occurred in
+// the thread's currently active split point, or in some ancestor of
+// the current split point.
+
+bool Thread::cutoff_occurred() const {
+
+  for (SplitPoint* sp = splitPoint; sp; sp = sp->parent)
+      if (sp->is_betaCutoff)
+          return true;
+  return false;
+}
+
+
+// is_available_to() checks whether the thread is available to help the thread with
+// threadID "master" at a split point. An obvious requirement is that thread must be
+// idle. With more than two threads, this is not by itself sufficient: If the thread
+// is the master of some active split point, it is only available as a slave to the
+// threads which are busy searching the split point at the top of "slave"'s split
+// point stack (the "helpful master concept" in YBWC terminology).
+
+bool Thread::is_available_to(int master) const {
+
+  if (state != AVAILABLE)
+      return false;
+
+  // Make a local copy to be sure doesn't become zero under our feet while
+  // testing next condition and so leading to an out of bound access.
+  int localActiveSplitPoints = activeSplitPoints;
+
+  // No active split points means that the thread is available as a slave for any
+  // other thread otherwise apply the "helpful master" concept if possible.
+  if (   !localActiveSplitPoints
+      || splitPoints[localActiveSplitPoints - 1].is_slave[master])
+      return true;
+
+  return false;
+}
+
+
 // read_uci_options() updates number of active threads and other internal
 // parameters according to the UCI options values. It is called before
 // to start a new search.
 // read_uci_options() updates number of active threads and other internal
 // parameters according to the UCI options values. It is called before
 // to start a new search.
@@ -68,7 +118,7 @@ void ThreadsManager::read_uci_options() {
 // init_threads() is called during startup. Initializes locks and condition
 // variables and launches all threads sending them immediately to sleep.
 
 // init_threads() is called during startup. Initializes locks and condition
 // variables and launches all threads sending them immediately to sleep.
 
-void ThreadsManager::init_threads() {
+void ThreadsManager::init() {
 
   int arg[MAX_THREADS];
 
 
   int arg[MAX_THREADS];
 
@@ -77,7 +127,7 @@ void ThreadsManager::init_threads() {
 
   // Threads will sent to sleep as soon as created, only main thread is kept alive
   activeThreads = 1;
 
   // Threads will sent to sleep as soon as created, only main thread is kept alive
   activeThreads = 1;
-  threads[0].state = THREAD_SEARCHING;
+  threads[0].state = Thread::SEARCHING;
 
   // Allocate pawn and material hash tables for main thread
   init_hash_tables();
 
   // Allocate pawn and material hash tables for main thread
   init_hash_tables();
@@ -97,7 +147,7 @@ void ThreadsManager::init_threads() {
   // Create and startup all the threads but the main that is already running
   for (int i = 1; i < MAX_THREADS; i++)
   {
   // Create and startup all the threads but the main that is already running
   for (int i = 1; i < MAX_THREADS; i++)
   {
-      threads[i].state = THREAD_INITIALIZING;
+      threads[i].state = Thread::INITIALIZING;
       arg[i] = i;
 
 #if !defined(_MSC_VER)
       arg[i] = i;
 
 #if !defined(_MSC_VER)
@@ -110,11 +160,11 @@ void ThreadsManager::init_threads() {
       if (!ok)
       {
           std::cout << "Failed to create thread number " << i << std::endl;
       if (!ok)
       {
           std::cout << "Failed to create thread number " << i << std::endl;
-          exit(EXIT_FAILURE);
+          ::exit(EXIT_FAILURE);
       }
 
       // Wait until the thread has finished launching and is gone to sleep
       }
 
       // Wait until the thread has finished launching and is gone to sleep
-      while (threads[i].state == THREAD_INITIALIZING) {}
+      while (threads[i].state == Thread::INITIALIZING) {}
   }
 }
 
   }
 }
 
@@ -122,7 +172,7 @@ void ThreadsManager::init_threads() {
 // exit_threads() is called when the program exits. It makes all the
 // helper threads exit cleanly.
 
 // exit_threads() is called when the program exits. It makes all the
 // helper threads exit cleanly.
 
-void ThreadsManager::exit_threads() {
+void ThreadsManager::exit() {
 
   // Force the woken up threads to exit idle_loop() and hence terminate
   allThreadsShouldExit = true;
 
   // Force the woken up threads to exit idle_loop() and hence terminate
   allThreadsShouldExit = true;
@@ -133,7 +183,7 @@ void ThreadsManager::exit_threads() {
       if (i != 0)
       {
           threads[i].wake_up();
       if (i != 0)
       {
           threads[i].wake_up();
-          while (threads[i].state != THREAD_TERMINATED) {}
+          while (threads[i].state != Thread::TERMINATED) {}
       }
 
       // Now we can safely destroy the locks and wait conditions
       }
 
       // Now we can safely destroy the locks and wait conditions
@@ -164,66 +214,15 @@ void ThreadsManager::init_hash_tables() {
 }
 
 
 }
 
 
-// cutoff_at_splitpoint() checks whether a beta cutoff has occurred in
-// the thread's currently active split point, or in some ancestor of
-// the current split point.
-
-bool ThreadsManager::cutoff_at_splitpoint(int threadID) const {
-
-  assert(threadID >= 0 && threadID < activeThreads);
-
-  SplitPoint* sp = threads[threadID].splitPoint;
-
-  for ( ; sp && !sp->betaCutoff; sp = sp->parent) {}
-  return sp != NULL;
-}
-
-
-// thread_is_available() checks whether the thread with threadID "slave" is
-// available to help the thread with threadID "master" at a split point. An
-// obvious requirement is that "slave" must be idle. With more than two
-// threads, this is not by itself sufficient:  If "slave" is the master of
-// some active split point, it is only available as a slave to the other
-// threads which are busy searching the split point at the top of "slave"'s
-// split point stack (the "helpful master concept" in YBWC terminology).
-
-bool ThreadsManager::thread_is_available(int slave, int master) const {
-
-  assert(slave >= 0 && slave < activeThreads);
-  assert(master >= 0 && master < activeThreads);
-  assert(activeThreads > 1);
-
-  if (threads[slave].state != THREAD_AVAILABLE || slave == master)
-      return false;
-
-  // Make a local copy to be sure doesn't change under our feet
-  int localActiveSplitPoints = threads[slave].activeSplitPoints;
-
-  // No active split points means that the thread is available as
-  // a slave for any other thread.
-  if (localActiveSplitPoints == 0 || activeThreads == 2)
-      return true;
-
-  // Apply the "helpful master" concept if possible. Use localActiveSplitPoints
-  // that is known to be > 0, instead of threads[slave].activeSplitPoints that
-  // could have been set to 0 by another thread leading to an out of bound access.
-  if (threads[slave].splitPoints[localActiveSplitPoints - 1].slaves[master])
-      return true;
-
-  return false;
-}
-
-
-// available_thread_exists() tries to find an idle thread which is available as
+// available_slave_exists() tries to find an idle thread which is available as
 // a slave for the thread with threadID "master".
 
 // a slave for the thread with threadID "master".
 
-bool ThreadsManager::available_thread_exists(int master) const {
+bool ThreadsManager::available_slave_exists(int master) const {
 
   assert(master >= 0 && master < activeThreads);
 
   assert(master >= 0 && master < activeThreads);
-  assert(activeThreads > 1);
 
   for (int i = 0; i < activeThreads; i++)
 
   for (int i = 0; i < activeThreads; i++)
-      if (thread_is_available(i, master))
+      if (i != master && threads[i].is_available_to(master))
           return true;
 
   return false;
           return true;
 
   return false;
@@ -259,7 +258,7 @@ void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const V
 
   // If no other thread is available to help us, or if we have too many
   // active split points, don't split.
 
   // If no other thread is available to help us, or if we have too many
   // active split points, don't split.
-  if (   !available_thread_exists(master)
+  if (   !available_slave_exists(master)
       || masterThread.activeSplitPoints >= MAX_ACTIVE_SPLIT_POINTS)
   {
       lock_release(&mpLock);
       || masterThread.activeSplitPoints >= MAX_ACTIVE_SPLIT_POINTS)
   {
       lock_release(&mpLock);
@@ -272,7 +271,7 @@ void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const V
   // Initialize the split point object
   splitPoint.parent = masterThread.splitPoint;
   splitPoint.master = master;
   // Initialize the split point object
   splitPoint.parent = masterThread.splitPoint;
   splitPoint.master = master;
-  splitPoint.betaCutoff = false;
+  splitPoint.is_betaCutoff = false;
   splitPoint.depth = depth;
   splitPoint.threatMove = threatMove;
   splitPoint.alpha = *alpha;
   splitPoint.depth = depth;
   splitPoint.threatMove = threatMove;
   splitPoint.alpha = *alpha;
@@ -285,22 +284,22 @@ void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const V
   splitPoint.nodes = 0;
   splitPoint.ss = ss;
   for (i = 0; i < activeThreads; i++)
   splitPoint.nodes = 0;
   splitPoint.ss = ss;
   for (i = 0; i < activeThreads; i++)
-      splitPoint.slaves[i] = 0;
+      splitPoint.is_slave[i] = false;
 
   masterThread.splitPoint = &splitPoint;
 
   // If we are here it means we are not available
 
   masterThread.splitPoint = &splitPoint;
 
   // If we are here it means we are not available
-  assert(masterThread.state != THREAD_AVAILABLE);
+  assert(masterThread.state != Thread::AVAILABLE);
 
   int workersCnt = 1; // At least the master is included
 
   // Allocate available threads setting state to THREAD_BOOKED
   for (i = 0; !Fake && i < activeThreads && workersCnt < maxThreadsPerSplitPoint; i++)
 
   int workersCnt = 1; // At least the master is included
 
   // Allocate available threads setting state to THREAD_BOOKED
   for (i = 0; !Fake && i < activeThreads && workersCnt < maxThreadsPerSplitPoint; i++)
-      if (thread_is_available(i, master))
+      if (i != master && threads[i].is_available_to(master))
       {
       {
-          threads[i].state = THREAD_BOOKED;
+          threads[i].state = Thread::BOOKED;
           threads[i].splitPoint = &splitPoint;
           threads[i].splitPoint = &splitPoint;
-          splitPoint.slaves[i] = 1;
+          splitPoint.is_slave[i] = true;
           workersCnt++;
       }
 
           workersCnt++;
       }
 
@@ -312,11 +311,11 @@ void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const V
   // Tell the threads that they have work to do. This will make them leave
   // their idle loop.
   for (i = 0; i < activeThreads; i++)
   // Tell the threads that they have work to do. This will make them leave
   // their idle loop.
   for (i = 0; i < activeThreads; i++)
-      if (i == master || splitPoint.slaves[i])
+      if (i == master || splitPoint.is_slave[i])
       {
       {
-          assert(i == master || threads[i].state == THREAD_BOOKED);
+          assert(i == master || threads[i].state == Thread::BOOKED);
 
 
-          threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
+          threads[i].state = Thread::WORKISWAITING; // This makes the slave to exit from idle_loop()
 
           if (useSleepingThreads && i != master)
               threads[i].wake_up();
 
           if (useSleepingThreads && i != master)
               threads[i].wake_up();
@@ -343,5 +342,5 @@ void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const V
 }
 
 // Explicit template instantiations
 }
 
 // Explicit template instantiations
-template void ThreadsManager::split<0>(Position&, SearchStack*, Value*, const Value, Value*, Depth, Move, int, MovePicker*, bool);
-template void ThreadsManager::split<1>(Position&, SearchStack*, Value*, const Value, Value*, Depth, Move, int, MovePicker*, bool);
+template void ThreadsManager::split<false>(Position&, SearchStack*, Value*, const Value, Value*, Depth, Move, int, MovePicker*, bool);
+template void ThreadsManager::split<true>(Position&, SearchStack*, Value*, const Value, Value*, Depth, Move, int, MovePicker*, bool);
index e5a198c88e764902d74ff6f509c4ef4075cefbb5..13121ca1175756ee4965f4af25e29dc339f7396b 100644 (file)
@@ -53,27 +53,32 @@ struct SplitPoint {
   volatile Value alpha;
   volatile Value bestValue;
   volatile int moveCount;
   volatile Value alpha;
   volatile Value bestValue;
   volatile int moveCount;
-  volatile bool betaCutoff;
-  volatile int slaves[MAX_THREADS];
-};
-
-// ThreadState type is used to represent thread's current state
-enum ThreadState
-{
-  THREAD_INITIALIZING,  // thread is initializing itself
-  THREAD_SEARCHING,     // thread is performing work
-  THREAD_AVAILABLE,     // thread is waiting for work
-  THREAD_BOOKED,        // other thread (master) has booked us as a slave
-  THREAD_WORKISWAITING, // master has ordered us to start
-  THREAD_TERMINATED     // we are quitting and thread is terminated
+  volatile bool is_betaCutoff;
+  volatile bool is_slave[MAX_THREADS];
 };
 
 
 };
 
 
-// We use per-thread Pawn and material hash 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.
+/// Thread struct is used to keep together all the thread related stuff like locks,
+/// state and especially split points. We also use per-thread pawn and material hash
+/// 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.
 
 struct Thread {
 
 struct Thread {
+
+  enum ThreadState
+  {
+    INITIALIZING,  // Thread is initializing itself
+    SEARCHING,     // Thread is performing work
+    AVAILABLE,     // Thread is waiting for work
+    BOOKED,        // Other thread (master) has booked us as a slave
+    WORKISWAITING, // Master has ordered us to start
+    TERMINATED     // We are quitting and thread is terminated
+  };
+
+  void wake_up();
+  bool cutoff_occurred() const;
+  bool is_available_to(int master) const;
+
   MaterialInfoTable materialTable;
   PawnInfoTable pawnTable;
   int maxPly;
   MaterialInfoTable materialTable;
   PawnInfoTable pawnTable;
   int maxPly;
@@ -83,18 +88,12 @@ struct Thread {
   SplitPoint* volatile splitPoint;
   volatile int activeSplitPoints;
   SplitPoint splitPoints[MAX_ACTIVE_SPLIT_POINTS];
   SplitPoint* volatile splitPoint;
   volatile int activeSplitPoints;
   SplitPoint splitPoints[MAX_ACTIVE_SPLIT_POINTS];
-
-  void wake_up() {
-    lock_grab(&sleepLock);
-    cond_signal(&sleepCond);
-    lock_release(&sleepLock);
-  }
 };
 
 
 };
 
 
-// ThreadsManager class is used to handle all the threads related stuff like init,
-// starting, parking and, the most important, launching a slave thread at a split
-// point. All the access to shared thread data is done through this class.
+/// ThreadsManager class is used to handle all the threads related stuff like init,
+/// starting, parking and, the most important, launching a slave thread at a split
+/// point. All the access to shared thread data is done through this class.
 
 class ThreadsManager {
   /* As long as the single ThreadsManager object is defined as a global we don't
 
 class ThreadsManager {
   /* As long as the single ThreadsManager object is defined as a global we don't
@@ -103,18 +102,16 @@ class ThreadsManager {
   */
 public:
   Thread& operator[](int threadID) { return threads[threadID]; }
   */
 public:
   Thread& operator[](int threadID) { return threads[threadID]; }
-  void init_threads();
-  void exit_threads();
+  void init();
+  void exit();
   void init_hash_tables();
 
   int min_split_depth() const { return minimumSplitDepth; }
   void init_hash_tables();
 
   int min_split_depth() const { return minimumSplitDepth; }
-  int active_threads() const { return activeThreads; }
-  void set_active_threads(int cnt) { activeThreads = cnt; }
+  int size() const { return activeThreads; }
+  void set_size(int cnt) { activeThreads = cnt; }
 
   void read_uci_options();
 
   void read_uci_options();
-  bool available_thread_exists(int master) const;
-  bool thread_is_available(int slave, int master) const;
-  bool cutoff_at_splitpoint(int threadID) const;
+  bool available_slave_exists(int master) const;
   void idle_loop(int threadID, SplitPoint* sp);
 
   template <bool Fake>
   void idle_loop(int threadID, SplitPoint* sp);
 
   template <bool Fake>
@@ -130,6 +127,6 @@ private:
   Thread threads[MAX_THREADS];
 };
 
   Thread threads[MAX_THREADS];
 };
 
-extern ThreadsManager ThreadsMgr;
+extern ThreadsManager Threads;
 
 #endif // !defined(THREAD_H_INCLUDED)
 
 #endif // !defined(THREAD_H_INCLUDED)