Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::async guaranteed to be called for functions returning void?

I've wrote the following code to test std::async() on functions returning void with GCC 4.8.2 on Ubuntu.

#include <future>
#include <iostream>

void functionTBC()
{
    std::cerr << "Print here\n";
}

int main(void)
{
#ifdef USE_ASYNC
    auto i = std::async(std::launch::async, functionTBC);
#else
    auto i = std::async(std::launch::deferred, functionTBC);
#endif
    //i.get();
    return 0;
}

If i.get(); is uncommented, the message "Print here" always exists; however, if i.get(); is commented out, "Print here" exists if and only if USE_ASYNC is defined (that is, std::launch::async always leads to message printed out while std::launch::deferred never).

Is this guaranteed behavior? What's the correct way to ensure the asynchronous call returning void to be executed?

like image 655
timrau Avatar asked May 29 '15 16:05

timrau


People also ask

Can async return void?

Event handlers naturally return void, so async methods return void so that you can have an asynchronous event handler. However, some semantics of an async void method are subtly different than the semantics of an async Task or async Task<T> method. Async void methods have different error-handling semantics.

What happens if you return in a void function?

A void function cannot return any values. But we can use the return statement. It indicates that the function is terminated.

What does STD async return?

With a std::async call the return value of the supplied function (as determined by std::result_of) sets the template type of the returned std::future: // function returns an int so std::async() returns a std::future<int> std::future<int> fut = std::async(std::launch::async, []{ return 1; });

Can you call return in a void function?

Void functions do not have a return type, but they can do return values.


1 Answers

std::launch::deferred means "do not run this until I .wait() or .get()".

As you never .get() or .wait()ed, it never ran.

void has nothing to do with this.

For std::launch::async, the standard states that the returned future's destructor (~future) will block until the task is complete (ie, has an implicit .wait()). This is violated by MSVC on purpose, because they disagreed with that design decision, and they are fighting to change the standard: in practice, this means that you cannot rely on any behavior at all from std::launch::async returned future if you want to future-proof your code.

Without implicit wait in ~future, it would be indeterminate if it actually invoked the function when main exited. It would either have happened, or not. Possibly you could invoke UB by having still-active threads at the end of main.

You may wonder what use deferred has: you can use it to queue up a computation for lazy evaluation.

like image 174
Yakk - Adam Nevraumont Avatar answered Nov 07 '22 00:11

Yakk - Adam Nevraumont