C++17 async: запуск метода this'блокирует весь объект
Я разрабатываю игру. Скажем, есть объект LoadingState с этими методами (и некоторыми другими):
- Создайте
- Обновить
- нагрузка
Обновление вызывается каждый раз, когда тактовые импульсы процессоров, в то время как create будет вызываться только один раз, и он должен вызывать функцию загрузки (асинхронно), чтобы загрузить некоторые игровые ресурсы. Асинхронный вызов load внутри функции create позволяет (теоретически) выполнить обновление с beling, вызываемого во время выполнения create/load. Этого, однако, не происходит.
До Visual Studio 2015 я использовал std:: async следующим образом:
std::async(&LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
После миграции на Visual Studio 2015 (C++17) и чтения того, что необходимо указать std:: launch, в противном случае может произойти непредвиденное поведение, асинхронность теперь вызывается так:
std::async(std::launch::async, &LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
Другими словами, мне кажется, что "this" блокируется std:: async, блокируя весь объект, не давая основному потоку вызвать update.
Более соответствующий код:
void LoadingState::onCreate()
{
std::vector<std::string> assets;
assets.push_back("Images/Scenario/wall.png");
assets.push_back("Images/Scenario/bigdummy.png");
assets.push_back("Images/Scenario/buildings.png");
assets.push_back("Images/Scenario/floor.png");
assets.push_back("Images/Scenario/terrain.png");
assets.push_back("Images/Scenario/trees.png");
// Load assets asynchronously
std::async(std::launch::async, &LoadingState::load, this, assets);
}
void LoadingState::load(std::vector<std::string> assets)
{
unsigned int count = 0;
unsigned int ratio = 100U / assets.size();
// Cache the asset accordingly
for (auto& asset : assets)
{
// Load and store the asset
// ...
// Asset loaded
count++;
// Calculate the progress by count
m_progress = count * ratio;
}
// If assets were skipped or progress would be like 98% due to truncation, normalize it
m_progress = 100U;
}
void LoadingState::update(float delta)
{
// ...
// If finished loading the resources, move on to playing state!
if (m_progress >= 100U) {
m_machine->next(new PlayingState(m_machine));
}
}
Что я тут недопонимаю?!
PS: до миграции все работало ровно.
1 ответ
std::async(std::launch::async, &LoadingState::load, this, assets);
future
вернулся async
будет блокировать в своем деструкторе до async
функция закончилась (в отличие от всех остальных future
объект). Поэтому вы должны захватить это future
и оставьте его в живых (перемещая, где это необходимо), пока вы не будете готовы к ответу.
Или вы можете просто прекратить использовать непонятные функции, такие как async
,
читая, что должен быть указан std::launch
Нет.