+// TimerThread::idle_loop() is where the timer thread waits Resolution milliseconds
+// and then calls check_time(). When not searching, thread sleeps until it's woken up.
+
+void TimerThread::idle_loop() {
+
+ while (!exit)
+ {
+ std::unique_lock<std::mutex> lk(mutex);
+
+ if (!exit)
+ sleepCondition.wait_for(lk, std::chrono::milliseconds(run ? Resolution : INT_MAX));
+
+ lk.unlock();
+
+ if (run)
+ check_time();
+ }
+}
+
+
+// MainThread::idle_loop() is where the main thread is parked waiting to be started
+// when there is a new search. The main thread will launch all the slave threads.
+
+void MainThread::idle_loop() {
+
+ while (!exit)
+ {
+ std::unique_lock<std::mutex> lk(mutex);
+
+ thinking = false;
+
+ while (!thinking && !exit)
+ {
+ Threads.sleepCondition.notify_one(); // Wake up the UI thread if needed
+ sleepCondition.wait(lk);
+ }
+
+ lk.unlock();
+
+ if (!exit)
+ {
+ searching = true;
+
+ Search::think();
+
+ assert(searching);
+
+ searching = false;
+ }
+ }
+}
+
+
+// ThreadPool::init() is called at startup to create and launch requested threads,
+// that will go immediately to sleep. We cannot use a c'tor because Threads is a
+// static object and we need a fully initialized engine at this point due to
+// allocation of Endgames in Thread c'tor.
+
+void ThreadPool::init() {
+
+ timer = new_thread<TimerThread>();
+ push_back(new_thread<MainThread>());
+ read_uci_options();
+}
+
+
+// ThreadPool::exit() terminates the threads before the program exits. Cannot be
+// done in d'tor because threads must be terminated before freeing us.
+
+void ThreadPool::exit() {
+
+ delete_thread(timer); // As first because check_time() accesses threads data
+
+ for (Thread* th : *this)
+ delete_thread(th);
+}
+
+
+// ThreadPool::read_uci_options() updates internal threads parameters from the
+// corresponding UCI options and creates/destroys threads to match the requested
+// number. Thread objects are dynamically allocated to avoid creating all possible
+// threads in advance (which include pawns and material tables), even if only a
+// few are to be used.
+
+void ThreadPool::read_uci_options() {
+
+ minimumSplitDepth = Options["Min Split Depth"] * ONE_PLY;
+ size_t requested = Options["Threads"];
+
+ assert(requested > 0);