bool available_thread_exists(int master) const;
bool thread_is_available(int slave, int master) const;
bool cutoff_at_splitpoint(int threadID) const;
- void wake_sleeping_thread(int threadID);
void idle_loop(int threadID, SplitPoint* sp);
template <bool Fake>
void split(Position& pos, SearchStack* ss, Value* alpha, const Value beta, Value* bestValue,
Depth depth, Move threatMove, int moveCount, MovePicker* mp, bool pvNode);
-
private:
Lock mpLock;
Depth minimumSplitDepth;
// Wake up needed threads and reset maxPly counter
for (int i = 0; i < ThreadsMgr.active_threads(); i++)
{
- ThreadsMgr.wake_sleeping_thread(i);
+ ThreadsMgr[i].wake_up();
ThreadsMgr[i].maxPly = 0;
}
// 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
+ while ( threadID >= activeThreads
+ || threads[threadID].state == THREAD_INITIALIZING
|| (useSleepingThreads && threads[threadID].state == THREAD_AVAILABLE))
{
assert(!sp || useSleepingThreads);
threads[threadID].state = THREAD_SEARCHING;
- // Copy SplitPoint position and search stack and call search()
+ // Copy split point position and search stack and call search()
// with SplitPoint template parameter set to true.
SearchStack ss[PLY_MAX_PLUS_2];
SplitPoint* tsp = threads[threadID].splitPoint;
// 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)
- wake_sleeping_thread(tsp->master);
+ if ( useSleepingThreads
+ && threadID != tsp->master
+ && 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
}
- // init_threads() is called during startup. It launches all helper threads,
- // and initializes the split point stack and the global locks and condition
- // objects.
+ // init_threads() is called during startup. Initializes locks and condition
+ // variables and launches all threads sending them immediately to sleep.
void ThreadsManager::init_threads() {
int i, arg[MAX_THREADS];
bool ok;
- // Initialize global locks
+ // This flag is needed to properly end the threads when program exits
+ allThreadsShouldExit = false;
+
+ // Threads will sent to sleep as soon as created, only main thread is kept alive
+ activeThreads = 1;
+
lock_init(&mpLock);
for (i = 0; i < MAX_THREADS; i++)
{
+ // Initialize thread and split point locks
lock_init(&threads[i].sleepLock);
cond_init(&threads[i].sleepCond);
- }
- // Initialize splitPoints[] locks
- for (i = 0; i < MAX_THREADS; i++)
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
lock_init(&(threads[i].splitPoints[j].lock));
- // Will be set just before program exits to properly end the threads
- allThreadsShouldExit = false;
-
- // Threads will be put all threads to sleep as soon as created
- activeThreads = 1;
-
- // All threads except the main thread should be initialized to THREAD_INITIALIZING
- threads[0].state = THREAD_SEARCHING;
- for (i = 1; i < MAX_THREADS; i++)
- threads[i].state = THREAD_INITIALIZING;
+ // All threads but first should be set to THREAD_INITIALIZING
+ threads[i].state = (i == 0 ? THREAD_SEARCHING : THREAD_INITIALIZING);
+ }
- // Launch the helper threads
+ // Create and startup the threads
for (i = 1; i < MAX_THREADS; i++)
{
arg[i] = i;
void ThreadsManager::exit_threads() {
- allThreadsShouldExit = true; // Let the woken up threads to exit idle_loop()
+ // Force the woken up threads to exit idle_loop() and hence terminate
+ allThreadsShouldExit = true;
- // Wake up all the threads and waits for termination
- for (int i = 1; i < MAX_THREADS; i++)
+ for (int i = 0; i < MAX_THREADS; i++)
{
- wake_sleeping_thread(i);
- while (threads[i].state != THREAD_TERMINATED) {}
- }
+ // Wake up all the threads and waits for termination
+ if (i != 0)
+ {
+ threads[i].wake_up();
+ while (threads[i].state != THREAD_TERMINATED) {}
+ }
+
+ // Now we can safely destroy the locks and wait conditions
+ lock_destroy(&threads[i].sleepLock);
+ cond_destroy(&threads[i].sleepCond);
- // Now we can safely destroy the locks
- for (int i = 0; i < MAX_THREADS; i++)
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
lock_destroy(&(threads[i].splitPoints[j].lock));
+ }
lock_destroy(&mpLock);
-
- // Now we can safely destroy the wait conditions
- for (int i = 0; i < MAX_THREADS; i++)
- {
- lock_destroy(&threads[i].sleepLock);
- cond_destroy(&threads[i].sleepCond);
- }
}
threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
if (useSleepingThreads && i != master)
- wake_sleeping_thread(i);
+ threads[i].wake_up();
}
// Everything is set up. The master thread enters the idle loop, from
}
- // wake_sleeping_thread() wakes up the thread with the given threadID
- // when it is time to start a new search.
-
- void ThreadsManager::wake_sleeping_thread(int threadID) {
-
- lock_grab(&threads[threadID].sleepLock);
- cond_signal(&threads[threadID].sleepCond);
- lock_release(&threads[threadID].sleepLock);
- }
-
-
/// RootMove and RootMoveList method's definitions
RootMove::RootMove() {