C++11: std::future and std::async

C++11 introduces support for asynchronous calls in a very easy way.

An asynchronous call is a method invocation that will be executed in a separate thread (or core or processor); so, the caller of the method does not wait for the result of the execution and continue doing what is next; in this way, the compiler/processor/operating system can optimise the execution of the program and execute several routines at the same time (given the now common multicore systems we all have at home and in our pockets!). The standard library provides the mechanisms to perform those asynchronous calls and store the results until the caller will actually need them.

Look at this piece of code:

#include <future>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

string reverse_string(const string& s)
{
	cout << "Reversing " << s << endl;
	string ss(s);
	reverse(ss.begin(), ss.end());
	return ss;
}

int main()
{
	future<string> f = async(reverse_string, "Roma tibi subito motibus ibit amor");
	auto g = async(reverse_string, "Anita lava la tina");
	auto h = async(reverse_string, "A man, a plan, a canal: Panama");
	
	cout << "SHOWING RESULTS...." << endl;
	
	cout << "R1: " << f.get() << endl << endl;
	cout << "R2: " << g.get() << endl << endl;
	cout << "R3: " << h.get() << endl << endl;
}

To compile this (in a Linux system, using gcc 4.7 in my case; I know that it works on Visual Studio 2012 too): you need to invoke the g++ compiler in this way:


g++ asynctest.cpp -o asynctest -std=c++11 -lpthread

You need to make explicit that you will be using the pthreads library because the g++ C++ threading implementation is based on it.

When executing the program, you will get something like this:


SHOWING RESULTS....
Reversing Roma tibi subito motibus ibit amor
R1: roma tibi subitom otibus ibit amoR

Reversing Anita lava la tina
R2: anit al aval atinA

Reversing A man, a plan, a canal: Panama
R3: amanaP :lanac a ,nalp a ,nam A

The “intrepid” reader looking at the program output will realize that the reverse_string function was executed when the get method was invoked; making the execution of this program, totally synchronous and with no taking advantages of multithreading.

The “problem” is that the default behavior of the async function performs a lazy execution of the function passed as parameter, turning the actual execution into synchronous. If we want an asynchronous execution, we should use an overload of the async function.

Look at my modified main function:

int main()
{
	future<string> f = async(launch::async, reverse_string, "Roma tibi subito motibus ibit amor");
	auto g = async(launch::async, reverse_string, "Anita lava la tina");
	auto h = async(launch::async, reverse_string, "A man, a plan, a canal: Panama");
	
	cout << "SHOWING RESULTS...." << endl;
	
	cout << "R1: " << f.get() << endl << endl;
	cout << "R2: " << g.get() << endl << endl;
	cout << "R3: " << h.get() << endl << endl;
}

Look at the launch::async parameter passed to the async function. Such parameter lets you execute your function asynchronously. You could also use this overload for lazy execution using the launch::deferred parameter instead of launch::async.

In my computer, the execution after my changes look like this:


SHOWING RESULTS....
Reversing Roma tibi subito motibus ibit amor
Reversing A man, a plan, a canal: Panama
Reversing Anita lava la tina
R1: roma tibi subitom otibus ibit amoR

R2: anit al aval atinA

R3: amanaP :lanac a ,nalp a ,nam A

Look that the order of execution is random and that the methods were executed asynchronously before actually showing their results.

The nice part of this? Everything! You can optimise your program to take advantage of the multicore systems with almost no effort!

How does the async function work?

It receives three (or two if using the overload of my first example) parameters:

1. The launch policy, that can be “launch::deferred” or “launch::async” (as explained above).
2. The pointer to a function, a functor or a lambda function which we want to execute asynchronously.
3. The parameters to be passed to the function passed as argument (similar to the bind function).

If the launch policy is set to “async”, it executes the method in a different thread.

What does the async function return?

It returns an object of type future<T> where T is the return type of the function passed as parameter to async. future abstracts all the information needed to store and return the result of executing the method asynchronously.

The method future<T>::get returns the result of executing the function asynchronously. If the launch policy is deferred, it executes the function in the same thread, otherwise, it returns the result of the asynchronuos execution (done in other thread). If the method is still being executed when future<T>::get is called, it waits until the asynchronous method finishes its execution and then returns the result.

Advertisements

One thought on “C++11: std::future and std::async

  1. Under Linux I needed the parameter -pthread instead of -lpthread as the article says.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s