From 1a414cd9cb274d9572c60fe4067671cd993ffb36 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Mon, 4 Feb 2013 22:38:42 +0100 Subject: [PATCH 1/1] Derive ThreadPool from std::vector Prefer sub-classing to composition in this case. No functional change. --- src/search.cpp | 16 ++++++++-------- src/thread.cpp | 38 +++++++++++++++++++++----------------- src/thread.h | 14 +++----------- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 49d18b50..84c62eec 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -229,22 +229,22 @@ void Search::think() { // Reset the threads, still sleeping: will be wake up at split time for (size_t i = 0; i < Threads.size(); i++) - Threads[i].maxPly = 0; + Threads[i]->maxPly = 0; Threads.sleepWhileIdle = Options["Use Sleeping Threads"]; // Set best timer interval to avoid lagging under time pressure. Timer is // used to check for remaining available thinking time. - Threads.timer_thread()->msec = + Threads.timer->msec = Limits.use_time_management() ? std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution)) : Limits.nodes ? 2 * TimerResolution : 100; - Threads.timer_thread()->notify_one(); // Wake up the recurring timer + Threads.timer->notify_one(); // Wake up the recurring timer id_loop(RootPos); // Let's start searching ! - Threads.timer_thread()->msec = 0; // Stop the timer + Threads.timer->msec = 0; // Stop the timer Threads.sleepWhileIdle = true; // Send idle threads to sleep if (Options["Use Search Log"]) @@ -1513,8 +1513,8 @@ split_point_start: // At split points actual search starts from here int selDepth = 0; for (size_t i = 0; i < Threads.size(); i++) - if (Threads[i].maxPly > selDepth) - selDepth = Threads[i].maxPly; + if (Threads[i]->maxPly > selDepth) + selDepth = Threads[i]->maxPly; for (size_t i = 0; i < uciPVSize; i++) { @@ -1744,9 +1744,9 @@ void check_time() { // Loop across all split points and sum accumulated SplitPoint nodes plus // all the currently active slaves positions. for (size_t i = 0; i < Threads.size(); i++) - for (int j = 0; j < Threads[i].splitPointsSize; j++) + for (int j = 0; j < Threads[i]->splitPointsSize; j++) { - SplitPoint& sp = Threads[i].splitPoints[j]; + SplitPoint& sp = Threads[i]->splitPoints[j]; sp.mutex.lock(); diff --git a/src/thread.cpp b/src/thread.cpp index 12a95271..1c5c67ba 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -186,7 +186,7 @@ void ThreadPool::init() { sleepWhileIdle = true; timer = new TimerThread(); - threads.push_back(new MainThread()); + push_back(new MainThread()); read_uci_options(); } @@ -197,8 +197,8 @@ void ThreadPool::exit() { delete timer; // As first because check_time() accesses threads data - for (size_t i = 0; i < threads.size(); i++) - delete threads[i]; + for (iterator it = begin(); it != end(); ++it) + delete *it; } @@ -215,13 +215,13 @@ void ThreadPool::read_uci_options() { assert(requested > 0); - while (threads.size() < requested) - threads.push_back(new Thread()); + while (size() < requested) + push_back(new Thread()); - while (threads.size() > requested) + while (size() > requested) { - delete threads.back(); - threads.pop_back(); + delete back(); + pop_back(); } } @@ -231,8 +231,8 @@ void ThreadPool::read_uci_options() { bool ThreadPool::slave_available(Thread* master) const { - for (size_t i = 0; i < threads.size(); i++) - if (threads[i]->is_available_to(master)) + for (const_iterator it = begin(); it != end(); ++it) + if ((*it)->is_available_to(master)) return true; return false; @@ -290,16 +290,20 @@ Value Thread::split(Position& pos, Stack* ss, Value alpha, Value beta, splitPointsSize++; activeSplitPoint = &sp; - size_t slavesCnt = 1; // Master is always included + size_t slavesCnt = 1; // This thread is always included - for (size_t i = 0; i < Threads.size() && !Fake; ++i) - if (Threads[i].is_available_to(this) && ++slavesCnt <= Threads.maxThreadsPerSplitPoint) + for (ThreadPool::iterator it = Threads.begin(); it != Threads.end() && !Fake; ++it) + { + Thread* slave = *it; + + if (slave->is_available_to(this) && ++slavesCnt <= Threads.maxThreadsPerSplitPoint) { - sp.slavesMask |= 1ULL << Threads[i].idx; - Threads[i].activeSplitPoint = &sp; - Threads[i].searching = true; // Slave leaves idle_loop() - Threads[i].notify_one(); // Could be sleeping + sp.slavesMask |= 1ULL << slave->idx; + slave->activeSplitPoint = &sp; + slave->searching = true; // Slave leaves idle_loop() + slave->notify_one(); // Could be sleeping } + } sp.mutex.unlock(); Threads.mutex.unlock(); diff --git a/src/thread.h b/src/thread.h index 76a2d843..786c5b67 100644 --- a/src/thread.h +++ b/src/thread.h @@ -138,21 +138,16 @@ struct TimerThread : public Thread { }; -/// ThreadPool class handles all the threads related stuff like init, starting, +/// ThreadPool struct handles all the threads related stuff like init, starting, /// parking and, the most important, launching a slave thread at a split point. /// All the access to shared thread data is done through this class. -class ThreadPool { +struct ThreadPool : public std::vector { -public: void init(); // No c'tor and d'tor, threads rely on globals that should void exit(); // be initialized and valid during the whole thread lifetime. - Thread& operator[](size_t id) { return *threads[id]; } - size_t size() const { return threads.size(); } - MainThread* main_thread() { return static_cast(threads[0]); } - TimerThread* timer_thread() { return timer; } - + MainThread* main_thread() { return static_cast((*this)[0]); } void read_uci_options(); bool slave_available(Thread* master) const; void wait_for_think_finished(); @@ -164,9 +159,6 @@ public: size_t maxThreadsPerSplitPoint; Mutex mutex; ConditionVariable sleepCondition; - -private: - std::vector threads; TimerThread* timer; }; -- 2.39.2