// 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
int ActiveThreads;
volatile bool AllThreadsShouldExit;
Thread threads[MAX_THREADS];
- Lock MPLock;
+ Lock MPLock, WaitLock;
WaitCondition WaitCond[MAX_THREADS];
};
const Value EasyMoveMargin = Value(0x200);
- /// Global variables
+ /// Namespace variables
+
+ // Book object
+ Book OpeningBook;
// Iteration counter
int Iteration;
UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch;
// Look for a book move, only during games, not tests
- if (UseTimeManagement && get_option_value_bool("OwnBook"))
+ if (UseTimeManagement && Options["OwnBook"].value<bool>())
{
- if (get_option_value_string("Book File") != OpeningBook.file_name())
- OpeningBook.open(get_option_value_string("Book File"));
+ if (Options["Book File"].value<std::string>() != OpeningBook.file_name())
+ OpeningBook.open(Options["Book File"].value<std::string>());
- Move bookMove = OpeningBook.get_move(pos, get_option_value_bool("Best Book Move"));
+ Move bookMove = OpeningBook.get_move(pos, Options["Best Book Move"].value<bool>());
if (bookMove != MOVE_NONE)
{
if (PonderSearch)
}
// Read UCI option values
- TT.set_size(get_option_value_int("Hash"));
- if (button_was_pressed("Clear Hash"))
+ TT.set_size(Options["Hash"].value<int>());
+ if (Options["Clear Hash"].value<bool>())
+ {
+ Options["Clear Hash"].set_value("false");
TT.clear();
+ }
- CheckExtension[1] = Depth(get_option_value_int("Check Extension (PV nodes)"));
- CheckExtension[0] = Depth(get_option_value_int("Check Extension (non-PV nodes)"));
- SingleEvasionExtension[1] = Depth(get_option_value_int("Single Evasion Extension (PV nodes)"));
- SingleEvasionExtension[0] = Depth(get_option_value_int("Single Evasion Extension (non-PV nodes)"));
- PawnPushTo7thExtension[1] = Depth(get_option_value_int("Pawn Push to 7th Extension (PV nodes)"));
- PawnPushTo7thExtension[0] = Depth(get_option_value_int("Pawn Push to 7th Extension (non-PV nodes)"));
- PassedPawnExtension[1] = Depth(get_option_value_int("Passed Pawn Extension (PV nodes)"));
- PassedPawnExtension[0] = Depth(get_option_value_int("Passed Pawn Extension (non-PV nodes)"));
- PawnEndgameExtension[1] = Depth(get_option_value_int("Pawn Endgame Extension (PV nodes)"));
- PawnEndgameExtension[0] = Depth(get_option_value_int("Pawn Endgame Extension (non-PV nodes)"));
- MateThreatExtension[1] = Depth(get_option_value_int("Mate Threat Extension (PV nodes)"));
- MateThreatExtension[0] = Depth(get_option_value_int("Mate Threat Extension (non-PV nodes)"));
-
- MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * ONE_PLY;
- MaxThreadsPerSplitPoint = get_option_value_int("Maximum Number of Threads per Split Point");
- MultiPV = get_option_value_int("MultiPV");
- UseLogFile = get_option_value_bool("Use Search Log");
+ CheckExtension[1] = Options["Check Extension (PV nodes)"].value<Depth>();
+ CheckExtension[0] = Options["Check Extension (non-PV nodes)"].value<Depth>();
+ SingleEvasionExtension[1] = Options["Single Evasion Extension (PV nodes)"].value<Depth>();
+ SingleEvasionExtension[0] = Options["Single Evasion Extension (non-PV nodes)"].value<Depth>();
+ PawnPushTo7thExtension[1] = Options["Pawn Push to 7th Extension (PV nodes)"].value<Depth>();
+ PawnPushTo7thExtension[0] = Options["Pawn Push to 7th Extension (non-PV nodes)"].value<Depth>();
+ PassedPawnExtension[1] = Options["Passed Pawn Extension (PV nodes)"].value<Depth>();
+ PassedPawnExtension[0] = Options["Passed Pawn Extension (non-PV nodes)"].value<Depth>();
+ PawnEndgameExtension[1] = Options["Pawn Endgame Extension (PV nodes)"].value<Depth>();
+ PawnEndgameExtension[0] = Options["Pawn Endgame Extension (non-PV nodes)"].value<Depth>();
+ MateThreatExtension[1] = Options["Mate Threat Extension (PV nodes)"].value<Depth>();
+ MateThreatExtension[0] = Options["Mate Threat Extension (non-PV nodes)"].value<Depth>();
+
+ MinimumSplitDepth = Options["Minimum Split Depth"].value<int>() * ONE_PLY;
+ MaxThreadsPerSplitPoint = Options["Maximum Number of Threads per Split Point"].value<int>();
+ MultiPV = Options["MultiPV"].value<int>();
+ UseLogFile = Options["Use Search Log"].value<bool>();
if (UseLogFile)
- LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app);
+ LogFile.open(Options["Search Log Filename"].value<std::string>().c_str(), std::ios::out | std::ios::app);
read_weights(pos.side_to_move());
// Set the number of active threads
- int newActiveThreads = get_option_value_int("Threads");
+ int newActiveThreads = Options["Threads"].value<int>();
if (newActiveThreads != ThreadsMgr.active_threads())
{
ThreadsMgr.set_active_threads(newActiveThreads);
init_eval(ThreadsMgr.active_threads());
}
+ // Wake up needed threads
+ for (int i = 1; i < newActiveThreads; i++)
+ ThreadsMgr.wake_sleeping_thread(i);
+
// Set thinking time
int myTime = time[pos.side_to_move()];
int myIncrement = increment[pos.side_to_move()];
if (UseLogFile)
LogFile.close();
+ // This makes all the threads to go to sleep
+ ThreadsMgr.set_active_threads(1);
+
return !Quit;
}
<< " time " << current_search_time() << endl;
// Print the best move and the ponder move to the standard output
- if (pv[0] == MOVE_NONE)
+ if (pv[0] == MOVE_NONE || MultiPV > 1)
{
pv[0] = rml.move(0);
pv[1] = MOVE_NONE;
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;
// 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
- || (!sp && threads[threadID].state == THREAD_AVAILABLE))
+ while (threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING)
{
assert(!sp);
assert(threadID != 0);
if (AllThreadsShouldExit)
break;
- lock_grab(&MPLock);
+ threads[threadID].state = THREAD_AVAILABLE;
- // Retest condition under lock protection
- if (!( threadID >= ActiveThreads
- || threads[threadID].state == THREAD_INITIALIZING
- || (!sp && threads[threadID].state == THREAD_AVAILABLE)))
- {
- lock_release(&MPLock);
- continue;
- }
+ lock_grab(&WaitLock);
- // Put thread to sleep
- threads[threadID].state = THREAD_AVAILABLE;
- cond_wait(&WaitCond[threadID], &MPLock);
- lock_release(&MPLock);
+ if (threadID >= ActiveThreads || threads[threadID].state == THREAD_INITIALIZING)
+ cond_wait(&WaitCond[threadID], &WaitLock);
+
+ lock_release(&WaitLock);
}
// If this thread has been assigned work, launch a search
// Initialize global locks
lock_init(&MPLock);
+ lock_init(&WaitLock);
for (i = 0; i < MAX_THREADS; i++)
cond_init(&WaitCond[i]);
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
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
lock_destroy(&(threads[i].splitPoints[j].lock));
+ lock_destroy(&WaitLock);
lock_destroy(&MPLock);
// Now we can safely destroy the wait conditions
assert(i == master || threads[i].state == THREAD_BOOKED);
threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()
- if (i != master)
- wake_sleeping_thread(i);
}
// Everything is set up. The master thread enters the idle loop, from
void ThreadsManager::wake_sleeping_thread(int threadID) {
- lock_grab(&MPLock);
+ lock_grab(&WaitLock);
cond_signal(&WaitCond[threadID]);
- lock_release(&MPLock);
+ lock_release(&WaitLock);
}