mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-10 22:31:40 +02:00
Fix crash on closing game during background image upscaling
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "../../lib/ArtifactUtils.h"
|
||||
#include "../../lib/AsyncRunner.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
#include "../../lib/entities/building/CBuilding.h"
|
||||
@@ -32,8 +33,6 @@
|
||||
#include "AIGateway.h"
|
||||
#include "Goals/Goals.h"
|
||||
|
||||
static tbb::task_arena executeActionAsyncArena;
|
||||
|
||||
namespace NKAI
|
||||
{
|
||||
|
||||
@@ -73,7 +72,7 @@ AIGateway::AIGateway()
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
nullkiller.reset(new Nullkiller());
|
||||
asyncTasks = std::make_unique<tbb::task_group>();
|
||||
asyncTasks = std::make_unique<AsyncRunner>();
|
||||
}
|
||||
|
||||
AIGateway::~AIGateway()
|
||||
@@ -593,11 +592,11 @@ void AIGateway::yourTurn(QueryID queryID)
|
||||
|
||||
nullkiller->makingTurnInterrupption.reset();
|
||||
|
||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this]()
|
||||
asyncTasks->run([this]()
|
||||
{
|
||||
ScopedThreadName guard("NKAI::makingTurn");
|
||||
makeTurn();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
void AIGateway::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID)
|
||||
@@ -1608,13 +1607,13 @@ void AIGateway::executeActionAsync(const std::string & description, const std::f
|
||||
if (!asyncTasks)
|
||||
throw std::runtime_error("Attempt to execute task on shut down AI state!");
|
||||
|
||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this, description, whatToDo]()
|
||||
asyncTasks->run([this, description, whatToDo]()
|
||||
{
|
||||
ScopedThreadName guard("NKAI::" + description);
|
||||
SET_GLOBAL_STATE(this);
|
||||
std::shared_lock gsLock(CGameState::mutex);
|
||||
whatToDo();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
void AIGateway::lostHero(HeroPtr h)
|
||||
|
@@ -22,8 +22,9 @@
|
||||
#include "Pathfinding/AIPathfinder.h"
|
||||
#include "Engine/Nullkiller.h"
|
||||
|
||||
#include <tbb/task_group.h>
|
||||
#include <tbb/task_arena.h>
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class AsyncRunner;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
namespace NKAI
|
||||
{
|
||||
@@ -74,7 +75,7 @@ public:
|
||||
AIStatus status;
|
||||
std::string battlename;
|
||||
std::shared_ptr<CCallback> myCb;
|
||||
std::unique_ptr<tbb::task_group> asyncTasks;
|
||||
std::unique_ptr<AsyncRunner> asyncTasks;
|
||||
|
||||
public:
|
||||
ObjectInstanceID selectedObject;
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "Goals/Goals.h"
|
||||
|
||||
#include "../../lib/ArtifactUtils.h"
|
||||
#include "../../lib/AsyncRunner.h"
|
||||
#include "../../lib/CThreadHelper.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
@@ -37,8 +38,6 @@
|
||||
|
||||
#include "AIhelper.h"
|
||||
|
||||
static tbb::task_arena executeActionAsyncArena;
|
||||
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
const double SAFE_ATTACK_CONSTANT = 1.5;
|
||||
@@ -78,7 +77,7 @@ struct SetGlobalState
|
||||
VCAI::VCAI()
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
asyncTasks = std::make_unique<tbb::task_group>();
|
||||
asyncTasks = std::make_unique<AsyncRunner>();
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
|
||||
@@ -653,11 +652,11 @@ void VCAI::yourTurn(QueryID queryID)
|
||||
status.startedTurn();
|
||||
|
||||
makingTurnInterrupption.reset();
|
||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this]()
|
||||
asyncTasks->run([this]()
|
||||
{
|
||||
ScopedThreadName guard("VCAI::makingTurn");
|
||||
makeTurn();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
void VCAI::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID)
|
||||
@@ -2510,13 +2509,13 @@ void VCAI::executeActionAsync(const std::string & description, const std::functi
|
||||
if (!asyncTasks)
|
||||
throw std::runtime_error("Attempt to execute task on shut down AI state!");
|
||||
|
||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this, description, whatToDo]()
|
||||
asyncTasks->run([this, description, whatToDo]()
|
||||
{
|
||||
ScopedThreadName guard("VCAI::" + description);
|
||||
SET_GLOBAL_STATE(this);
|
||||
std::shared_lock gsLock(CGameState::mutex);
|
||||
whatToDo();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
void VCAI::lostHero(HeroPtr h)
|
||||
|
@@ -23,13 +23,11 @@
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "Pathfinding/AIPathfinder.h"
|
||||
|
||||
#include <tbb/task_group.h>
|
||||
#include <tbb/task_arena.h>
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct QuestInfo;
|
||||
class PathfinderCache;
|
||||
class AsyncRunner;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@@ -108,7 +106,7 @@ public:
|
||||
|
||||
std::shared_ptr<CCallback> myCb;
|
||||
|
||||
std::unique_ptr<tbb::task_group> asyncTasks;
|
||||
std::unique_ptr<AsyncRunner> asyncTasks;
|
||||
ThreadInterruption makingTurnInterrupption;
|
||||
|
||||
public:
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "GameEngineUser.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
|
||||
#include "../lib/AsyncRunner.h"
|
||||
#include "../lib/CThreadHelper.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
|
||||
@@ -86,6 +87,8 @@ GameEngine::GameEngine()
|
||||
sound().setVolume((ui32)settings["general"]["sound"].Float());
|
||||
music().setVolume((ui32)settings["general"]["music"].Float());
|
||||
cursorHandlerInstance = std::make_unique<CursorHandler>();
|
||||
|
||||
asyncTasks = std::make_unique<AsyncRunner>();
|
||||
}
|
||||
|
||||
void GameEngine::handleEvents()
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
class AsyncRunner;
|
||||
class Rect;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@@ -52,6 +53,7 @@ private:
|
||||
std::unique_ptr<IMusicPlayer> musicPlayerInstance;
|
||||
std::unique_ptr<CursorHandler> cursorHandlerInstance;
|
||||
std::unique_ptr<IVideoPlayer> videoPlayerInstance;
|
||||
std::unique_ptr<AsyncRunner> asyncTasks;
|
||||
|
||||
IGameEngineUser *engineUser = nullptr;
|
||||
|
||||
@@ -68,6 +70,7 @@ public:
|
||||
EventDispatcher & events();
|
||||
InputHandler & input();
|
||||
|
||||
AsyncRunner & async() { return *asyncTasks; }
|
||||
IGameEngineUser & user() { return *engineUser; }
|
||||
ISoundPlayer & sound() { return *soundPlayerInstance; }
|
||||
IMusicPlayer & music() { return *musicPlayerInstance; }
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "../GameEngine.h"
|
||||
#include "../render/IScreenHandler.h"
|
||||
|
||||
#include "../../lib/AsyncRunner.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
@@ -256,8 +257,6 @@ std::shared_ptr<const ISharedImage> SDLImageShared::scaleInteger(int factor, SDL
|
||||
|
||||
SDLImageShared::SDLImageShared(const SDLImageShared * from, int integerScaleFactor, EScalingAlgorithm algorithm)
|
||||
{
|
||||
static tbb::task_arena upscalingArena;
|
||||
|
||||
upscalingInProgress = true;
|
||||
|
||||
auto scaler = std::make_shared<SDLImageScaler>(from->surf, Rect(from->margins, from->fullSize), true);
|
||||
@@ -273,7 +272,7 @@ SDLImageShared::SDLImageShared(const SDLImageShared * from, int integerScaleFact
|
||||
};
|
||||
|
||||
if(settings["video"]["asyncUpscaling"].Bool())
|
||||
upscalingArena.enqueue(scalingTask);
|
||||
ENGINE->async().run(scalingTask);
|
||||
else
|
||||
scalingTask();
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "../client/windows/CMessage.h"
|
||||
#include "../client/windows/InfoWindows.h"
|
||||
|
||||
#include "../lib/AsyncRunner.h"
|
||||
#include "../lib/CConsoleHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../lib/CThreadHelper.h"
|
||||
@@ -417,6 +418,9 @@ int main(int argc, char * argv[])
|
||||
vstd::clear_pointer(graphics);
|
||||
}
|
||||
|
||||
// must be executed before reset - since unique_ptr resets pointer to null before calling destructor
|
||||
ENGINE->async().wait();
|
||||
|
||||
ENGINE.reset();
|
||||
|
||||
vstd::clear_pointer(LIBRARY);
|
||||
|
40
lib/AsyncRunner.h
Normal file
40
lib/AsyncRunner.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* AsyncRunner.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <tbb/task_group.h>
|
||||
#include <tbb/task_arena.h>
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class AsyncRunner : boost::noncopyable
|
||||
{
|
||||
tbb::task_arena arena;
|
||||
tbb::task_group taskGroup;
|
||||
|
||||
public:
|
||||
template <typename Functor>
|
||||
void run(Functor && f)
|
||||
{
|
||||
arena.enqueue(taskGroup.defer(std::forward<Functor>(f)));
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
taskGroup.wait();
|
||||
}
|
||||
|
||||
~AsyncRunner()
|
||||
{
|
||||
wait();
|
||||
}
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@@ -693,6 +693,7 @@ set(lib_MAIN_HEADERS
|
||||
|
||||
AI_Base.h
|
||||
ArtifactUtils.h
|
||||
AsyncRunner.h
|
||||
BattleFieldHandler.h
|
||||
CAndroidVMHelper.h
|
||||
CArtHandler.h
|
||||
|
Reference in New Issue
Block a user