thread: 将 QThread 继续替换为 std::thread
已知问题: UI上黑白圈都按下后,需要点一次开始,才开始自对弈。 以下不易理解,待修改: void stopThreads() { aiThread[BLACK]->start_searching(); aiThread[WHITE]->start_searching(); }
This commit is contained in:
parent
86e96eb5af
commit
0d5667f8de
227
src/aithread.cpp
227
src/aithread.cpp
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue