From 55dcd9cc5aebbf8b9255c01e44e6cb5d36e59e81 Mon Sep 17 00:00:00 2001 From: DragonAura Date: Thu, 26 Jan 2023 00:16:32 +0800 Subject: [PATCH] refactor(CAPI): :lock: fix busy waiting --- CAPI/API/include/Communication.h | 5 +- CAPI/API/include/logic.h | 2 + CAPI/API/src/Communication.cpp | 14 ++++- CAPI/API/src/logic.cpp | 105 ++++++++++++++++--------------- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/CAPI/API/include/Communication.h b/CAPI/API/include/Communication.h index b1e678a..34682b8 100644 --- a/CAPI/API/include/Communication.h +++ b/CAPI/API/include/Communication.h @@ -10,6 +10,7 @@ #include "structures.h" #include #include +#include #include #include "ConcurrentQueue.hpp" @@ -18,7 +19,7 @@ class Logic; class Communication { public: - Communication(std::string sIP, std::string sPort); + Communication(std::string sIP, std::string sPort, std::mutex& mtx, std::condition_variable& cv); ~Communication() { } @@ -54,6 +55,8 @@ private: bool haveNewMessage = false; protobuf::MessageToClient message2Client; ConcurrentQueue> messageQueue; + std::mutex& mtxMessage; + std::condition_variable& cvMessage; }; #endif diff --git a/CAPI/API/include/logic.h b/CAPI/API/include/logic.h index dfc80dc..f578489 100644 --- a/CAPI/API/include/logic.h +++ b/CAPI/API/include/logic.h @@ -58,9 +58,11 @@ private: mutable std::mutex mtxAI; mutable std::mutex mtxState; mutable std::mutex mtxBuffer; + mutable std::mutex mtxMessage; std::condition_variable cvBuffer; std::condition_variable cvAI; + std::condition_variable cvMessage; // 信息队列 std::queue> messageQueue; diff --git a/CAPI/API/src/Communication.cpp b/CAPI/API/src/Communication.cpp index e189409..a43b48e 100644 --- a/CAPI/API/src/Communication.cpp +++ b/CAPI/API/src/Communication.cpp @@ -2,10 +2,14 @@ #include "utils.hpp" #include "structures.h" #include +#include +#include using grpc::ClientContext; -Communication::Communication(std::string sIP, std::string sPort) +Communication::Communication(std::string sIP, std::string sPort, std::mutex& mtx, std::condition_variable& cv) : + mtxMessage(mtx), + cvMessage(cv) { std::string aim = sIP + ':' + sPort; auto channel = grpc::CreateChannel(aim, grpc::InsecureChannelCredentials()); @@ -242,7 +246,13 @@ void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, T auto MessageReader = THUAI6Stub->AddPlayer(&context, playerMsg); while (MessageReader->Read(&message2Client)) - haveNewMessage = true; + { + { + std::lock_guard lock(mtxMessage); + haveNewMessage = true; + } + cvMessage.notify_one(); + } }; std::thread(tMessage).detach(); } diff --git a/CAPI/API/src/logic.cpp b/CAPI/API/src/logic.cpp index 3ce9a3a..fcaf85f 100644 --- a/CAPI/API/src/logic.cpp +++ b/CAPI/API/src/logic.cpp @@ -187,56 +187,58 @@ void Logic::ProcessMessage() pComm->ReadMessage(playerID); while (gameState != THUAI6::GameState::GameEnd) { - if (pComm->HaveMessage2Client()) { - logger->debug("Get message from server!"); - auto clientMsg = pComm->GetMessage2Client(); - gameState = Proto2THUAI6::gameStateDict[clientMsg.game_state()]; - switch (gameState) - { - case THUAI6::GameState::GameStart: - logger->info("Game Start!"); - - // 重新读取玩家的guid,guid确保人类在前屠夫在后 - playerGUIDs.clear(); - for (auto human : clientMsg.human_message()) - playerGUIDs.push_back(human.guid()); - for (auto butcher : clientMsg.butcher_message()) - playerGUIDs.push_back(butcher.guid()); - currentState->guids = playerGUIDs; - bufferState->guids = playerGUIDs; - - LoadBuffer(clientMsg); - - AILoop = true; - UnBlockAI(); - - break; - case THUAI6::GameState::GameRunning: - // 重新读取玩家的guid,guid确保人类在前屠夫在后 - playerGUIDs.clear(); - for (auto human : clientMsg.human_message()) - playerGUIDs.push_back(human.guid()); - for (auto butcher : clientMsg.butcher_message()) - playerGUIDs.push_back(butcher.guid()); - currentState->guids = playerGUIDs; - bufferState->guids = playerGUIDs; - - LoadBuffer(clientMsg); - break; - case THUAI6::GameState::GameEnd: - AILoop = false; - { - std::lock_guard lock(mtxBuffer); - bufferUpdated = true; - counterBuffer = -1; - } - cvBuffer.notify_one(); - logger->info("Game End!"); - break; - default: - logger->debug("Unknown GameState!"); - } + std::unique_lock lock(mtxMessage); + cvMessage.wait(lock, [this]() + { return pComm->HaveMessage2Client(); }); + } + logger->debug("Get message from server!"); + auto clientMsg = pComm->GetMessage2Client(); + gameState = Proto2THUAI6::gameStateDict[clientMsg.game_state()]; + switch (gameState) + { + case THUAI6::GameState::GameStart: + logger->info("Game Start!"); + + // 重新读取玩家的guid,guid确保人类在前屠夫在后 + playerGUIDs.clear(); + for (auto human : clientMsg.human_message()) + playerGUIDs.push_back(human.guid()); + for (auto butcher : clientMsg.butcher_message()) + playerGUIDs.push_back(butcher.guid()); + currentState->guids = playerGUIDs; + bufferState->guids = playerGUIDs; + + LoadBuffer(clientMsg); + + AILoop = true; + UnBlockAI(); + + break; + case THUAI6::GameState::GameRunning: + // 重新读取玩家的guid,guid确保人类在前屠夫在后 + playerGUIDs.clear(); + for (auto human : clientMsg.human_message()) + playerGUIDs.push_back(human.guid()); + for (auto butcher : clientMsg.butcher_message()) + playerGUIDs.push_back(butcher.guid()); + currentState->guids = playerGUIDs; + bufferState->guids = playerGUIDs; + + LoadBuffer(clientMsg); + break; + case THUAI6::GameState::GameEnd: + AILoop = false; + { + std::lock_guard lock(mtxBuffer); + bufferUpdated = true; + counterBuffer = -1; + } + cvBuffer.notify_one(); + logger->info("Game End!"); + break; + default: + logger->debug("Unknown GameState!"); } } }; @@ -428,8 +430,7 @@ const std::vector Logic::GetPlayerGUIDs() const bool Logic::TryConnection() { logger->info("Try to connect to server..."); - bool result = pComm->TryConnection(playerID); - return result; + return pComm->TryConnection(playerID); } void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool file, bool print, bool warnOnly) @@ -461,7 +462,7 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool f logger->info("****************************"); // 建立与服务器之间通信的组件 - pComm = std::make_unique(IP, port); + pComm = std::make_unique(IP, port, mtxMessage, cvMessage); // 构造timer if (playerType == THUAI6::PlayerType::HumanPlayer)