mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-21 00:19:29 +02:00
Better handling of AI shutdown
This commit is contained in:
@ -884,7 +884,15 @@ void AIGateway::makeTurn()
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
endTurn();
|
||||
}
|
||||
catch (const TerminationRequestedException & e)
|
||||
{
|
||||
logAi->debug("Making turn thread has been interrupted. We'll end without calling endTurn.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
|
||||
|
@ -260,7 +260,7 @@ int CBattleCallback::sendRequest(const CPackForServer & request)
|
||||
{
|
||||
logGlobal->trace("We'll wait till request %d is answered.\n", requestID);
|
||||
auto gsUnlocker = vstd::makeUnlockSharedGuardIf(CGameState::mutex, unlockGsWhenWaiting);
|
||||
CClient::waitingRequest.waitWhileContains(requestID);
|
||||
cl->waitingRequest.waitWhileContains(requestID);
|
||||
}
|
||||
return requestID;
|
||||
}
|
||||
|
@ -653,6 +653,8 @@ void CServerHandler::showHighScoresAndEndGameplay(PlayerColor player, bool victo
|
||||
|
||||
void CServerHandler::endGameplay()
|
||||
{
|
||||
client->finishGameplay();
|
||||
|
||||
// Game is ending
|
||||
// Tell the network thread to reach a stable state
|
||||
sendClientDisconnecting();
|
||||
@ -671,6 +673,7 @@ void CServerHandler::endGameplay()
|
||||
|
||||
void CServerHandler::restartGameplay()
|
||||
{
|
||||
client->finishGameplay();
|
||||
client->endGame();
|
||||
client.reset();
|
||||
|
||||
|
@ -46,8 +46,6 @@
|
||||
#include "lib/CAndroidVMHelper.h"
|
||||
#endif
|
||||
|
||||
ThreadSafeVector<int> CClient::waitingRequest;
|
||||
|
||||
CPlayerEnvironment::CPlayerEnvironment(PlayerColor player_, CClient * cl_, std::shared_ptr<CCallback> mainCallback_)
|
||||
: player(player_),
|
||||
cl(cl_),
|
||||
@ -181,17 +179,21 @@ void CClient::endNetwork()
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::finishGameplay()
|
||||
{
|
||||
waitingRequest.requestTermination();
|
||||
|
||||
//suggest interfaces to finish their stuff (AI should interrupt any bg working threads)
|
||||
for(auto & i : playerint)
|
||||
i.second->finish();
|
||||
}
|
||||
|
||||
void CClient::endGame()
|
||||
{
|
||||
#if SCRIPTING_ENABLED
|
||||
clientScripts.reset();
|
||||
#endif
|
||||
|
||||
//suggest interfaces to finish their stuff (AI should interrupt any bg working threads)
|
||||
for(auto & i : playerint)
|
||||
i.second->finish();
|
||||
|
||||
{
|
||||
logNetwork->info("Ending current game!");
|
||||
removeGUI();
|
||||
|
||||
@ -199,7 +201,6 @@ void CClient::endGame()
|
||||
vstd::clear_pointer(gs);
|
||||
|
||||
logNetwork->info("Deleted mapHandler and gameState.");
|
||||
}
|
||||
|
||||
CPlayerInterface::battleInt.reset();
|
||||
playerint.clear();
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <vcmi/Environment.h>
|
||||
|
||||
#include "../lib/IGameCallback.h"
|
||||
#include "../lib/ConditionalWait.h"
|
||||
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -50,8 +52,15 @@ class ThreadSafeVector
|
||||
std::vector<T> items;
|
||||
std::mutex mx;
|
||||
std::condition_variable cond;
|
||||
std::atomic<bool> isTerminating = false;
|
||||
|
||||
public:
|
||||
void requestTermination()
|
||||
{
|
||||
isTerminating = true;
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
TLock lock(mx);
|
||||
@ -61,6 +70,8 @@ public:
|
||||
|
||||
void pushBack(const T & item)
|
||||
{
|
||||
assert(!isTerminating);
|
||||
|
||||
TLock lock(mx);
|
||||
items.push_back(item);
|
||||
cond.notify_all();
|
||||
@ -68,14 +79,18 @@ public:
|
||||
|
||||
void waitWhileContains(const T & item)
|
||||
{
|
||||
//FIXME: should throw exception on destruction
|
||||
TLock lock(mx);
|
||||
while(vstd::contains(items, item))
|
||||
cond.wait(lock);
|
||||
|
||||
if (isTerminating)
|
||||
throw TerminationRequestedException();
|
||||
}
|
||||
|
||||
bool tryRemovingElement(const T & item) //returns false if element was not present
|
||||
{
|
||||
assert(!isTerminating);
|
||||
|
||||
TLock lock(mx);
|
||||
auto itr = vstd::find(items, item);
|
||||
if(itr == items.end()) //not in container
|
||||
@ -129,6 +144,7 @@ public:
|
||||
|
||||
void save(const std::string & fname);
|
||||
void endNetwork();
|
||||
void finishGameplay();
|
||||
void endGame();
|
||||
|
||||
void initMapHandler();
|
||||
@ -139,7 +155,7 @@ public:
|
||||
void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, PlayerColor color, bool battlecb = false);
|
||||
void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, PlayerColor color, bool needCallback = true);
|
||||
|
||||
static ThreadSafeVector<int> waitingRequest; //FIXME: make this normal field (need to join all threads before client destruction)
|
||||
ThreadSafeVector<int> waitingRequest;
|
||||
|
||||
void handlePack(CPackForClient & pack); //applies the given pack and deletes it
|
||||
int sendRequest(const CPackForServer & request, PlayerColor player); //returns ID given to that request
|
||||
|
@ -882,7 +882,7 @@ void ApplyClientNetPackVisitor::visitEndAction(EndAction & pack)
|
||||
void ApplyClientNetPackVisitor::visitPackageApplied(PackageApplied & pack)
|
||||
{
|
||||
callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::requestRealized, &pack);
|
||||
if(!CClient::waitingRequest.tryRemovingElement(pack.requestID))
|
||||
if(!cl.waitingRequest.tryRemovingElement(pack.requestID))
|
||||
logNetwork->warn("Surprising server message! PackageApplied for unknown requestID!");
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user