1

I've got a big .txt file full of words and I want to read them in a set<string> in my c++ application. Since reading it will pause execution of main for about 1-2 seconds I want to do it in a different thread without having to await the result.

Inside my Engine.cpp I've got:

void Engine::Run()
{
    std::string path = "..\\" + Constants::DictionaryFilePath;
    std::ifstream ifs(path);
    InputReader* reader = new InputReader(ifs);

    auto f = std::async(std::launch::async, &InputReader::ReadAll, reader);
    //Helpers::all_words = f.get();
    **//Helpers::all_words is a static set inside class Helpers**

    Console::SetSize(CONSOLE_WIDTH, CONSOLE_HEIGHT);

    while (true)
    {
        GameMenu* menu = new GameMenu(new GameStarter());
        menu->Run();

        Console::SetCursorPosition(0, 45);
        std::cout << Messages::EnterToPlayEscToEnd << std::endl;

        char c;
        c = Console::ReadKey();

        while (c != ENTER && c != ESCAPE)
        {
            c = Console::ReadKey();
//use f.get()'s result here
        }

        if (c == ESCAPE)
        {
            Console::Clear();
            delete menu;
            break;
        }
    }

    delete reader;
}

And in my InputReader:

std::set<std::string> InputReader::ReadAll() const
{
    std::cout << "STARTING" << std::endl; // debug

    std::set<std::string> result;

    std::string word;
    while (ifs >> word)
    {
        result.insert(word);
    }

    return result;
}

The problem is that even std::launch::async property, the thread won't start right off. It does only if it hits f.get() which still pauses until the thread's work is finished.

My question is how do I start this ReadAll function without having to wait for the result and get the result later?

  • You probably need to provide a bit more code... It will be hard for us to reproduce your problem with this. Where do you run the first snippet? Where do you store the future? When/where do you use it to get `all_words`? – Holt Jan 22 '18 at 10:47
  • 1
    What are you doing in main thread after creating `f` to determine that it does not start? I mean you can't just let `f` (which is local variable) get out of scope. Also it makes little sense for reader to have `WriteAll` method. – user7860670 Jan 22 '18 at 10:47
  • Edited with more code provided. The word "write" was a typo sorry. –  Jan 22 '18 at 10:53
  • Did you try by using `f.get()` directly inside the loop (I'm assuming you currently use it somewhere else, otherwise you'd have put it in the code)? OT, you should use `unique_ptr` instead of these manual allocations and deallocations. – Holt Jan 22 '18 at 11:12
  • @Holt yes, I did try it. Same happens, the thread starts execution only whenever f.get() is called. As for the unique_ptr, i don't feel the need to include another header for a simple example like this. It's a test program –  Jan 22 '18 at 11:21
  • [Confusion about threads launched by std::async with std::launch::async parameter](https://stackoverflow.com/questions/30810305/confusion-about-threads-launched-by-stdasync-with-stdlaunchasync-parameter). – user7860670 Jan 22 '18 at 11:26
  • @StoyanLupov I cannot reproduce your problem with this: https://gist.github.com/Holt59/d6db8f4b009a53e3d819af3d9ef0a1ee Either this generates the same problem on your platform, in which case you'd have to add information regarding it, and if it does not, you'll need to provide an example that we can run on our own. – Holt Jan 22 '18 at 11:39
  • @VTT, he is probably comparing the output of std::cout << "STARTING" << std::endl; and std::cout << Messages::EnterToPlayEscToEnd << std::endl; to say the thread has not started. But because he is not doing much between starting the async operation and calling the get, it is possible the second std::cout is executed before the async operation is launched in a new thread. Try to put a sleep of like 2 seconds before the while loop to see truly if the async is not being started. – falopsy Jan 22 '18 at 11:45
  • Fixed it. The problem was that the future f was not being used any more down in the main thread so the compiler calls its destructor too early and as we know: `Futures returned by async() with async launch policy wait in their destructor for the associated shared state to become ready. This prevents a situation in which the associated thread continues to run, and there is no longer a means to wait for it to complete because the associated future has been destroyed.` I just put a f.get() after my while loop to keep the future alive –  Jan 23 '18 at 20:14

0 Answers0