thread: 将 QThread 继续替换为 std::thread

已知问题:

UI上黑白圈都按下后,需要点一次开始,才开始自对弈。

以下不易理解,待修改:
    void stopThreads()
    {
        aiThread[BLACK]->start_searching();
        aiThread[WHITE]->start_searching();
    }
This commit is contained in:
Calcitem 2020-10-03 10:31:47 +08:00
parent 86e96eb5af
commit 0d5667f8de
4 changed files with 136 additions and 113 deletions

View File

@ -35,6 +35,7 @@ using namespace std;
Value MTDF(Position *pos, Sanmill::Stack<Position> &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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lk(mutex);
quit();
}
///////////////
void AiThread::setAi(Position *p)
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lk(mutex);
quit();
}
void AiThread::resume()
{
std::lock_guard<std::mutex> lk(mutex);
cv.notify_one(); // Wake up anyone
}
void AiThread::stop()
{
if (isFinished() || !isRunning())
return;
if (!isInterruptionRequested()) {
requestInterruption();
std::lock_guard<std::mutex> lk(mutex);
quit();
searching = true;
cv.notify_one(); // Wake up anyone
}
}
///////////////
Depth AiThread::adjustDepth()
{
Depth d = 0;

View File

@ -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()
{

View File

@ -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();
}
}

View File

@ -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();
}
}