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

Нет.

Другие вопросы по тегам