From 0d5667f8dea1c5e3d2a948e788c6e634fd476e8d Mon Sep 17 00:00:00 2001 From: Calcitem Date: Sat, 3 Oct 2020 10:31:47 +0800 Subject: [PATCH] =?UTF-8?q?thread:=20=E5=B0=86=20QThread=20=E7=BB=A7?= =?UTF-8?q?=E7=BB=AD=E6=9B=BF=E6=8D=A2=E4=B8=BA=20std::thread?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 已知问题: UI上黑白圈都按下后,需要点一次开始,才开始自对弈。 以下不易理解,待修改: void stopThreads() { aiThread[BLACK]->start_searching(); aiThread[WHITE]->start_searching(); } --- src/aithread.cpp | 227 +++++++++++++++++++---------------- src/aithread.h | 8 +- src/ui/qt/gamecontroller.cpp | 4 +- src/ui/qt/gamecontroller.h | 10 +- 4 files changed, 136 insertions(+), 113 deletions(-) diff --git a/src/aithread.cpp b/src/aithread.cpp index 99628eba..53d497fe 100644 --- a/src/aithread.cpp +++ b/src/aithread.cpp @@ -35,6 +35,7 @@ using namespace std; Value MTDF(Position *pos, Sanmill::Stack &ss, Value firstguess, Depth depth, Depth originDepth, Move &bestMove); AiThread::AiThread(int color, QObject *parent) : + stdThread(&AiThread::idle_loop, this), QThread(parent), timeLimit(3600) { @@ -51,24 +52,141 @@ AiThread::AiThread(int color, QObject *parent) : client = new Client(nullptr, clientPort); } #endif // TRAINING_MODE + + wait_for_search_finished(); } AiThread::~AiThread() { //delete server; - //delete client; + //delete client + + assert(!searching); - stop(); + exit = true; quit(); - wait(); + start_searching(); + stdThread.join(); } +/// Thread::start_searching() wakes up the thread that will start the search + +void AiThread::start_searching() +{ + quit(); + + std::lock_guard lk(mutex); + searching = true; + cv.notify_one(); // Wake up the thread in idle_loop() +} + +/// Thread::wait_for_search_finished() blocks on the condition variable +/// until the thread has finished searching. + +void AiThread::wait_for_search_finished() +{ + std::unique_lock lk(mutex); + cv.wait(lk, [&] { return !searching; }); +} + + +void AiThread::idle_loop() // idle_loop() +{ +#ifdef DEBUG_MODE + int iTemp = 0; +#endif + + Color sideToMove = NOCOLOR; + + loggerDebug("Thread %d start\n", us); + + bestvalue = lastvalue = VALUE_ZERO; + + while (true) { + std::unique_lock lk(mutex); + searching = false; + +#if 0 + sideToMove = rootPos->sideToMove; + + // TODO + if (sideToMove != us) { + cv.notify_one(); // Wake up anyone waiting for search finished + cv.wait(lk, [&] { return searching; }); + + if (exit) + return; + + lk.unlock(); + continue; + } +#endif + + cv.notify_one(); // Wake up anyone waiting for search finished + cv.wait(lk, [&] { return searching; }); + + if (exit) + return; + + emit searchStarted(); + lk.unlock(); + + if (rootPos == nullptr) { + continue; + } + + setPosition(rootPos); + +#ifdef OPENING_BOOK + // gameOptions.getOpeningBook() + if (!openingBookDeque.empty()) { + char obc[16] = { 0 }; + sq2str(obc); + strCommand = obc; + emitCommand(); + } else { +#endif + if (search() == 3) { + loggerDebug("Draw\n\n"); + strCommand = "draw"; + emitCommand(); + } else { + strCommand = nextMove(); + if (strCommand != "" && strCommand != "error!") { + emitCommand(); + } + } +#ifdef OPENING_BOOK + } +#endif + + emit searchFinished(); + +// lk.lock(); +// cv.wait(lk, [&] { return searching; }); +// lk.unlock(); + } + + loggerDebug("Thread %d quit\n", us); +} + +void AiThread::act() +{ + if (isFinished() || !isRunning()) + return; + + std::lock_guard lk(mutex); + quit(); +} + + +/////////////// + void AiThread::setAi(Position *p) { std::lock_guard lk(mutex); this->rootPos = p; - setPosition(p); #ifdef TRANSPOSITION_TABLE_ENABLE #ifdef CLEAR_TRANSPOSITION_TABLE @@ -79,10 +197,8 @@ void AiThread::setAi(Position *p) void AiThread::setAi(Position *p, int tl) { - std::lock_guard lk(mutex); + setAi(p); - this->rootPos = p; - setPosition(p); timeLimit = tl; } @@ -149,8 +265,7 @@ void AiThread::analyze(Color c) cout << *p << "\n" << endl; cout << std::dec; - switch (p->get_phase()) - { + switch (p->get_phase()) { case PHASE_PLACING: cout << "摆子阶段" << endl; break; @@ -243,100 +358,6 @@ out: cout << endl << endl; } -void AiThread::run() // idle_loop() -{ -#ifdef DEBUG_MODE - int iTemp = 0; -#endif - - Color sideToMove = NOCOLOR; - - loggerDebug("Thread %d start\n", us); - - bestvalue = lastvalue = VALUE_ZERO; - - while (!isInterruptionRequested()) { - std::unique_lock lk(mutex); - searching = false; - - sideToMove = rootPos->sideToMove; - - if (sideToMove != us) { - cv.wait(lk); - lk.unlock(); - continue; - } - - setPosition(rootPos); - emit searchStarted(); - lk.unlock(); - -#ifdef OPENING_BOOK - // gameOptions.getOpeningBook() - if (!openingBookDeque.empty()) { - char obc[16] = { 0 }; - sq2str(obc); - strCommand = obc; - emitCommand(); - } else { -#endif - if (search() == 3) { - loggerDebug("Draw\n\n"); - strCommand = "draw"; - emitCommand(); - } else { - strCommand = nextMove(); - if (strCommand != "" && strCommand != "error!") { - emitCommand(); - } - } -#ifdef OPENING_BOOK - } -#endif - - emit searchFinished(); - - lk.lock(); - if (!isInterruptionRequested()) { - cv.wait(lk); - } - lk.unlock(); - } - - loggerDebug("Thread %d quit\n", us); -} - -void AiThread::act() -{ - if (isFinished() || !isRunning()) - return; - - std::lock_guard lk(mutex); - quit(); -} - -void AiThread::resume() -{ - std::lock_guard lk(mutex); - cv.notify_one(); // Wake up anyone -} - -void AiThread::stop() -{ - if (isFinished() || !isRunning()) - return; - - if (!isInterruptionRequested()) { - requestInterruption(); - std::lock_guard lk(mutex); - quit(); - searching = true; - cv.notify_one(); // Wake up anyone - } -} - -/////////////// - Depth AiThread::adjustDepth() { Depth d = 0; diff --git a/src/aithread.h b/src/aithread.h index 4174dd40..6a1e02ee 100644 --- a/src/aithread.h +++ b/src/aithread.h @@ -30,6 +30,7 @@ #include "client.h" #include "test.h" #include "position.h" +#include "thread_win32_osx.h" class AiThread : public QThread { @@ -39,6 +40,7 @@ private: std::mutex mutex; std::condition_variable cv; bool exit = false, searching = true; // Set before starting std::thread + NativeThread stdThread; string strCommand; @@ -56,14 +58,14 @@ signals: public slots: void act(); // Force move, not quit thread - void resume(); - void stop(); + void start_searching(); void emitCommand(); public: void setAi(Position *p); void setAi(Position *p, int time); - void run() override; + void idle_loop(); + void wait_for_search_finished(); Server *getServer() { diff --git a/src/ui/qt/gamecontroller.cpp b/src/ui/qt/gamecontroller.cpp index f1c3d7ce..c1f1f2bf 100644 --- a/src/ui/qt/gamecontroller.cpp +++ b/src/ui/qt/gamecontroller.cpp @@ -353,11 +353,11 @@ void GameController::setEngine(int color, bool arg) if (arg) { aiThread[color]->setAi(&position); if (aiThread[color]->isRunning()) - aiThread[color]->resume(); + aiThread[color]->start_searching(); else aiThread[color]->start(); } else { - aiThread[color]->stop(); + aiThread[color]->start_searching(); } } diff --git a/src/ui/qt/gamecontroller.h b/src/ui/qt/gamecontroller.h index a7539a63..ff426b82 100644 --- a/src/ui/qt/gamecontroller.h +++ b/src/ui/qt/gamecontroller.h @@ -279,19 +279,19 @@ public slots: void stopAndWaitAiThreads() { if (isAiPlayer[BLACK]) { - aiThread[BLACK]->stop(); + aiThread[BLACK]->start_searching(); aiThread[BLACK]->wait(); } if (isAiPlayer[WHITE]) { - aiThread[WHITE]->stop(); + aiThread[WHITE]->start_searching(); aiThread[WHITE]->wait(); } } void stopThreads() { - aiThread[BLACK]->stop(); - aiThread[WHITE]->stop(); + aiThread[BLACK]->start_searching(); + aiThread[WHITE]->start_searching(); } void waitThreads() @@ -309,7 +309,7 @@ public slots: void resumeAiThreads(Color sideToMove) { if (isAiPlayer[sideToMove]) { - aiThread[sideToMove]->resume(); + aiThread[sideToMove]->start_searching(); } }