summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
35b6079)
To sync UI with main thread it is enough a single
condition variable because here we have a single
producer / single consumer design pattern.
Two condition variables are strictly needed just for
many producers / many consumers case.
Note that this is possible because now we don't send to
sleep idle threads anymore while searching, so that now
only UI can wake up the main thread and we can use the
same ConditionVariable for both threads.
The natural consequence is to retire wait_for_think_finished()
and move all the logic under MainThread class, yielding the
rename of teh function to join()
No functional change.
else
{
Threads.start_thinking(pos, limits, st);
else
{
Threads.start_thinking(pos, limits, st);
- Threads.wait_for_think_finished();
+ Threads.main()->join();
nodes += Search::RootPos.nodes_searched();
}
}
nodes += Search::RootPos.nodes_searched();
}
}
while (!thinking && !exit)
{
while (!thinking && !exit)
{
- Threads.sleepCondition.notify_one(); // Wake up the UI thread if needed
+ sleepCondition.notify_one(); // Wake up the UI thread if needed
sleepCondition.wait(lk);
}
sleepCondition.wait(lk);
}
+// MainThread::join() waits for main thread to finish the search
+
+void MainThread::join() {
+
+ std::unique_lock<Mutex> lk(mutex);
+ sleepCondition.wait(lk, [&]{ return !thinking; });
+}
+
+
// 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
// 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
-// ThreadPool::wait_for_think_finished() waits for main thread to finish the search
-
-void ThreadPool::wait_for_think_finished() {
-
- std::unique_lock<Mutex> lk(main()->mutex);
- sleepCondition.wait(lk, [&]{ return !main()->thinking; });
-}
-
-
// 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) {
// 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) {
- wait_for_think_finished();
SearchTime = now(); // As early as possible
SearchTime = now(); // As early as possible
struct MainThread : public Thread {
virtual void idle_loop();
struct MainThread : public Thread {
virtual void idle_loop();
volatile bool thinking = true; // Avoid a race with start_thinking()
};
volatile bool thinking = true; // Avoid a race with start_thinking()
};
MainThread* main() { return static_cast<MainThread*>(at(0)); }
void read_uci_options();
Thread* available_slave(const SplitPoint* sp) const;
MainThread* main() { return static_cast<MainThread*>(at(0)); }
void read_uci_options();
Thread* available_slave(const SplitPoint* sp) const;
- void wait_for_think_finished();
void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
Depth minimumSplitDepth;
void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
Depth minimumSplitDepth;
- ConditionVariable sleepCondition;
} while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
} while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
- Threads.wait_for_think_finished(); // Cannot quit whilst the search is running
+ Threads.main()->join(); // Cannot quit whilst the search is running