+
+// 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
+ timer = nullptr;
+
+ for (Thread* th : *this)
+ delete_thread(th);
+
+ clear(); // Get rid of stale pointers
+}
+
+
+// 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);
+
+ 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
+// to join SplitPoint 'sp'.
+
+Thread* ThreadPool::available_slave(const SplitPoint* sp) const {
+
+ for (Thread* th : *this)
+ if (th->can_join(sp))
+ return th;
+
+ return nullptr;
+}
+
+
+// ThreadPool::start_thinking() wakes up the main thread sleeping in
+// MainThread::idle_loop() and starts a new search, then returns immediately.
+
+void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
+ StateStackPtr& states) {
+ main()->join();