Browse Source

refactor(CAPI): 🔒 fix busy waiting

tags/0.1.0
DragonAura 3 years ago
parent
commit
55dcd9cc5a
4 changed files with 71 additions and 55 deletions
  1. +4
    -1
      CAPI/API/include/Communication.h
  2. +2
    -0
      CAPI/API/include/logic.h
  3. +12
    -2
      CAPI/API/src/Communication.cpp
  4. +53
    -52
      CAPI/API/src/logic.cpp

+ 4
- 1
CAPI/API/include/Communication.h View File

@@ -10,6 +10,7 @@
#include "structures.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#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<std::pair<int64_t, std::string>> messageQueue;
std::mutex& mtxMessage;
std::condition_variable& cvMessage;
};

#endif

+ 2
- 0
CAPI/API/include/logic.h View File

@@ -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<std::pair<int64_t, std::string>> messageQueue;


+ 12
- 2
CAPI/API/src/Communication.cpp View File

@@ -2,10 +2,14 @@
#include "utils.hpp"
#include "structures.h"
#include <thread>
#include <mutex>
#include <condition_variable>

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<std::mutex> lock(mtxMessage);
haveNewMessage = true;
}
cvMessage.notify_one();
}
};
std::thread(tMessage).detach();
}

+ 53
- 52
CAPI/API/src/logic.cpp View File

@@ -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<std::mutex> lock(mtxBuffer);
bufferUpdated = true;
counterBuffer = -1;
}
cvBuffer.notify_one();
logger->info("Game End!");
break;
default:
logger->debug("Unknown GameState!");
}
std::unique_lock<std::mutex> 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<std::mutex> 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<int64_t> 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<Communication>(IP, port);
pComm = std::make_unique<Communication>(IP, port, mtxMessage, cvMessage);

// 构造timer
if (playerType == THUAI6::PlayerType::HumanPlayer)


Loading…
Cancel
Save