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