Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does async always use another thread/core/process in C++?

As I know async executes a function in another thread/process/core and doesn't block the main thread, but is that always the case?

I have following code:

async(launch::async,[]() {     Sleep(1000);     puts("async"); }); puts("main"); 

It prints async main, so does that mean that the main thread waits until async finishes?

If I change to following:

auto f = async(launch::async,[]() // add "auto f = " {     Sleep(1000);     puts("async"); }); puts("main"); 

It prints main async. This makes it seem like main doesn't wait for async to finish.

like image 495
Person.Junkie Avatar asked Mar 22 '17 12:03

Person.Junkie


People also ask

Does async run on another thread?

No, it does not. It MAY start another thread internally and return that task, but the general idea is that it does not run on any thread.

Does async use multiple threads?

Async programming is about non-blocking execution between functions, and we can apply async with single-threaded or multithreaded programming. So, multithreading is one form of asynchronous programming.

Does STD async run on a separate thread?

The function template async runs the function f asynchronously (potentially in a separate thread which might be a part of a thread pool) and returns a std::future that will eventually hold the result of that function call. 1) Behaves as if (2) is called with policy being std::launch::async | std::launch::deferred.

Does STD async create new thread?

One nice thing about std::async is that it manages a thread pool under the hood. So there is no worry that every time we invoke std::async a new thread is launched.


2 Answers

As I know async executes a function in another thread/process/core and don't block main thread, but does it happens always?

std::async is guaranteed to execute on a separate thread only if std::launch::async is passed as the first argument:

  • std::launch::async: a new thread is launched to execute the task asynchronously
  • std::launch::deferred the task is executed on the calling thread the first time its result is requested (lazy evaluation)

The default launch policy is std::launch::async | std::launch::deferred.


std::async returns std::future. std::future's destructor will block only if the future was returned from std::async:

these actions will not block for the shared state to become ready, except that it may block if all of the following are true: the shared state was created by a call to std::async, the shared state is not yet ready, and this was the last reference to the shared state


  • In your first code snippet, you create an rvalue expression which is immediately destroyed - therefore "async" will be printed before "main".

    1. Async anonymous function is created and starts executing.

    2. Async anonymous function is destroyed.

      • main execution is blocked until the function is completed.

      • "async" is printed.

    3. main execuction resumes.

      • "main" is printed.

  • In your second code snippet, you create an lvalue expression whose lifetime is bound to the variable f. f will be destroyed at the end of the main function's scope - therefore "main" will be printed before "async" due to the Delay(1000).

    1. Async anonymous function is created and starts executing.

      • There's a Delay(1000) that delays "async" from being printed immediately.
    2. main execution continues.

      • "main" is printed.
    3. End of main's scope.

    4. Async anonymous function is destroyed.

      • main execution is blocked until the function is completed.

      • "async" is printed.

like image 176
Vittorio Romeo Avatar answered Sep 18 '22 13:09

Vittorio Romeo


It prints async main, so does that mean that the main thread waits until async finishes?

Yes it does, but that is because you do not capture the returned future from async. async is special in that the future returned from it blocks in the destructor until the thread completes. Since you do not capture the returned future

async(launch::async,[]() {     Sleep(1000);     puts("async"); }); 

must finish before progress is made in the current thread as that returned future is destroyed at the end of the expression.

It prints main async. This makes it seem like main doesn't wait for async to finish.

Which is what you really want when you call async. Since you have captured the future your main thread is allowed to continue on while the asynchronis task is completed. Since you have a delay in that thread main is going to print before the thread.

like image 45
NathanOliver Avatar answered Sep 19 '22 13:09

NathanOliver