-// Explicit template instantiations
-template void Thread::split<false>(Position&, const Stack*, Value, Value, Value*, Move*, Depth, Move, int, MovePicker*, int, bool);
-template void Thread::split< true>(Position&, const Stack*, Value, Value, Value*, Move*, Depth, Move, int, MovePicker*, int, bool);
+
+// 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);
+
+ // If zero (default) then set best minimum split depth automatically
+ if (!minimumSplitDepth)
+ minimumSplitDepth = requested < 8 ? 4 * ONE_PLY : 7 * ONE_PLY;
+
+ while (size() < requested)
+ push_back(new_thread<Thread>());
+
+ while (size() > requested)
+ {
+ delete_thread(back());
+ pop_back();
+ }
+}
+
+
+// ThreadPool::available_slave() tries to find an idle thread which is available
+// as a slave for the thread 'master'.
+
+Thread* ThreadPool::available_slave(const Thread* master) const {
+
+ for (Thread* th : *this)
+ if (th->available_to(master))
+ return th;
+
+ return nullptr;
+}