From 42a53446b0db72910faf2d5d6b44bd22200717dc Mon Sep 17 00:00:00 2001 From: QueensGambit Date: Fri, 11 Feb 2022 18:34:59 +0100 Subject: [PATCH] Handle flooding of UCI-commands (close #81) --- engine/src/agents/agent.cpp | 18 ++++++++++++++---- engine/src/agents/agent.h | 8 ++++++++ engine/src/agents/mctsagent.cpp | 8 ++++---- engine/src/agents/mctsagent.h | 3 --- engine/src/uci/crazyara.cpp | 12 +++++++----- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/engine/src/agents/agent.cpp b/engine/src/agents/agent.cpp index 35343cbd..6167eafe 100644 --- a/engine/src/agents/agent.cpp +++ b/engine/src/agents/agent.cpp @@ -54,7 +54,7 @@ void Agent::set_best_move(size_t moveCounter) Agent::Agent(NeuralNetAPI* net, PlaySettings* playSettings, bool verbose): NeuralNetAPIUser(net), - playSettings(playSettings), verbose(verbose) + playSettings(playSettings), verbose(verbose), isRunning(false) { } @@ -70,8 +70,19 @@ Action Agent::get_best_action() return evalInfo->bestMove; } +void Agent::lock() +{ + runnerMutex.lock(); +} + +void Agent::unlock() +{ + runnerMutex.unlock(); +} + void Agent::perform_action() { + isRunning = true; evalInfo->start = chrono::steady_clock::now(); this->evaluate_board_state(); evalInfo->end = chrono::steady_clock::now(); @@ -83,9 +94,8 @@ void Agent::perform_action() #else info_bestmove(StateConstants::action_to_uci(evalInfo->bestMove, state->is_chess960())); #endif - - - + isRunning = false; + runnerMutex.unlock(); } void run_agent_thread(Agent* agent) diff --git a/engine/src/agents/agent.h b/engine/src/agents/agent.h index 654d2bce..dfefa5d9 100644 --- a/engine/src/agents/agent.h +++ b/engine/src/agents/agent.h @@ -58,7 +58,11 @@ class Agent : public NeuralNetAPIUser PlaySettings* playSettings; StateObj* state; EvalInfo* evalInfo; + // protect the isRunning attribute and makes sure that the stop() command can only be called after the search has actually been started + mutex runnerMutex; bool verbose; + // boolean which can be triggered by "stop" from std-in to stop the current search + bool isRunning; public: Agent(NeuralNetAPI* net, PlaySettings* playSettings, bool verbose); @@ -100,6 +104,10 @@ class Agent : public NeuralNetAPIUser * @return Action */ Action get_best_action(); + + void lock(); + + void unlock(); }; } diff --git a/engine/src/agents/mctsagent.cpp b/engine/src/agents/mctsagent.cpp index e5b15877..c82ba5b9 100644 --- a/engine/src/agents/mctsagent.cpp +++ b/engine/src/agents/mctsagent.cpp @@ -45,7 +45,6 @@ MCTSAgent::MCTSAgent(NeuralNetAPI *netSingle, vector>& opponentsNextRoot(nullptr), lastValueEval(-1.0f), reusedFullTree(false), - isRunning(false), overallNPS(0.0f), nbNPSentries(0), threadManager(nullptr), @@ -340,26 +339,27 @@ void MCTSAgent::run_mcts_search() ThreadManagerParams tParams(curMovetime, 250, is_game_sceneario(searchLimits), can_prolong_search(rootNode->plies_from_null()/2, timeManager->get_thresh_move())); threadManager = make_unique(&tData, &tInfo, &tParams); unique_ptr tManager = make_unique(run_thread_manager, threadManager.get()); - isRunning = true; - + runnerMutex.unlock(); for (size_t i = 0; i < searchSettings->threads; ++i) { threads[i]->join(); } threadManager->kill(); tManager->join(); delete[] threads; - isRunning = false; } void MCTSAgent::stop() { + runnerMutex.lock(); if (!isRunning) { + runnerMutex.unlock(); return; } if (threadManager != nullptr) { threadManager->stop_search(); } isRunning = false; + runnerMutex.unlock(); } void MCTSAgent::print_root_node() diff --git a/engine/src/agents/mctsagent.h b/engine/src/agents/mctsagent.h index 89a39c36..c3abee60 100644 --- a/engine/src/agents/mctsagent.h +++ b/engine/src/agents/mctsagent.h @@ -70,9 +70,6 @@ class MCTSAgent : public Agent // boolean which indicates if the same node was requested twice for analysis bool reusedFullTree; - // boolean which can be triggered by "stop" from std-in to stop the current search - bool isRunning; - // saves the overall nps for each move during the game float overallNPS; size_t avgDepth; diff --git a/engine/src/uci/crazyara.cpp b/engine/src/uci/crazyara.cpp index d358f1d5..6c33e43a 100644 --- a/engine/src/uci/crazyara.cpp +++ b/engine/src/uci/crazyara.cpp @@ -168,8 +168,10 @@ void CrazyAra::prepare_search_config_structs() } } -void CrazyAra::go(StateObj* state, istringstream &is, EvalInfo& evalInfo) { - +void CrazyAra::go(StateObj* state, istringstream &is, EvalInfo& evalInfo) +{ + wait_to_finish_last_search(); + ongoingSearch = true; prepare_search_config_structs(); string token; @@ -186,15 +188,15 @@ void CrazyAra::go(StateObj* state, istringstream &is, EvalInfo& evalInfo) { else if (token == "movetime") is >> searchLimits.movetime; else if (token == "infinite") searchLimits.infinite = true; } - wait_to_finish_last_search(); - ongoingSearch = true; if (useRawNetwork) { rawAgent->set_search_settings(state, &searchLimits, &evalInfo); + rawAgent->lock(); // lock() rawAgent to avoid calling stop() immediatly mainSearchThread = thread(run_agent_thread, rawAgent.get()); } else { mctsAgent->set_search_settings(state, &searchLimits, &evalInfo); + mctsAgent->lock(); // lock() mctsAgent to avoid calling stop() immediatly mainSearchThread = thread(run_agent_thread, mctsAgent.get()); } } @@ -211,7 +213,6 @@ void CrazyAra::go(const string& fen, string goCommand, EvalInfo& evalInfo) position(state.get(), is); istringstream isGoCommand(goCommand); go(state.get(), isGoCommand, evalInfo); - wait_to_finish_last_search(); } void CrazyAra::wait_to_finish_last_search() @@ -226,6 +227,7 @@ void CrazyAra::stop_search() { if (mctsAgent != nullptr) { mctsAgent->stop(); + wait_to_finish_last_search(); } }