Browse Source

Merge pull request #89 from DragonAura/dev

perf(CAPI): 🔒 fix busy waiting
tags/0.1.0
Timothy Liu GitHub 3 years ago
parent
commit
69ef710f34
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 58 deletions
  1. +4
    -1
      CAPI/API/include/Communication.h
  2. +12
    -6
      CAPI/API/src/Communication.cpp
  3. +46
    -51
      CAPI/API/src/logic.cpp

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

@@ -10,7 +10,9 @@
#include "structures.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>
#include "ConcurrentQueue.hpp"

class Logic;
@@ -44,7 +46,6 @@ public:

bool TryConnection(int64_t playerID);
protobuf::MessageToClient GetMessage2Client();
bool HaveMessage2Client();
void AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, THUAI6::HumanType humanType, THUAI6::ButcherType butcherType);

void ReadMessage(int64_t playerID);
@@ -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

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

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

using grpc::ClientContext;

@@ -198,15 +200,13 @@ bool Communication::TryConnection(int64_t playerID)

protobuf::MessageToClient Communication::GetMessage2Client()
{
std::unique_lock<std::mutex> lock(mtxMessage);
cvMessage.wait(lock, [this]()
{ return haveNewMessage; });
haveNewMessage = false;
return message2Client;
}

bool Communication::HaveMessage2Client()
{
return haveNewMessage;
}

std::optional<std::pair<int64_t, std::string>> Communication::GetMessage()
{
return messageQueue.tryPop();
@@ -242,7 +242,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();
}

+ 46
- 51
CAPI/API/src/logic.cpp View File

@@ -187,58 +187,54 @@ void Logic::ProcessMessage()
pComm->ReadMessage(playerID);
while (gameState != THUAI6::GameState::GameEnd)
{
if (pComm->HaveMessage2Client())
auto clientMsg = pComm->GetMessage2Client(); // 在获得新消息之前阻塞
logger->debug("Get message from server!");
gameState = Proto2THUAI6::gameStateDict[clientMsg.game_state()];
switch (gameState)
{
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!");
}
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;
default:
logger->debug("Unknown GameState!");
break;
}
}
AILoop = false;
{
std::lock_guard<std::mutex> lock(mtxBuffer);
bufferUpdated = true;
counterBuffer = -1;
}
cvBuffer.notify_one();
logger->info("Game End!");
};
std::thread(messageThread).detach();
}
@@ -428,8 +424,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)


Loading…
Cancel
Save