C++11's async Template
C++11 brings rich support for threading to the language, and one of the features that really works for me is the function template async. This provides a great mechanism for spinning off worker threads and easily collecting their results. In this article, I'll show you how I used async to introduce threading to C++ beginners in a nice, non-threatening fashion.
C/C++ and Threads
Even though the languages lacked standardized support for threading, people have been writing multithreaded C and C++ programs for quite a long time. Libraries like pthreads work pretty well and give you a shot at reasonable portability. But I found that beginners would often stumble when using these as their introduction to multithreading.
The biggest annoyance for beginners would have to be the ability to pass parameters to threads, and to return values from threads. The pthreads library handled this in a conventional way for a C API, requiring all threads to have the same function signature — which relied on void pointers, dynamic allocation, and casting. Plenty of places for the newcomer to stumble.
And returning data from a thread to the caller? You're on your own. Ad hoc methods are easy enough to implement, but again, it's just one more place to make a mistake.
C++11 async()
C++11 solves most of these problems quite nicely with its thread support. In particular, for straightforward worker thread applications, the new async function template is perfect.
When using async(), a thread is modeled as a standard C++ function, as is the case with most other libraries. However, you can pass your choic e of parameters to the library — full type safety is observed, and you can pass values by copy or reference.
The function prototype for async is a bit of a mess, but in a nutshell, you call async with the following arguments:
-
A launch policy of either
std::launch::async, which asks the runtime to create an asynchronous thread, or std::launch::deferred, which indicates you simply want to defer the function call until a later time (lazy evaluati on.) This argument is optional — if you omit it your function will use the default policy.
The name of the function you are calling.
The arguments to be passed to the function. Normally these are passed just as you would when calling the function, but if you wish to pass an argument by reference, you need to wrap it in a call to std::ref().
The actual prototype is shown below:
template< class Function, class... Args >
std::future<typename std::result_of<Function(Args...)>::type>
async( std::launch policy, Function&& f, Args&&... args );
You'll note a few instances of C++11 variadic template syntax — the dot-dot-dot (not really an ellipsis) following the word class in the template type parameter list, and following the argument name Args. In both usages, this syntax means 0 or more arguments of this type. (How these variadic arguments are processed is a topic for another post.) The key point is that the function template async is instantiated to accept a typesafe list of arguments that have to match the function you are using to instantiate a thread.
My Teaching Example
To give students a feel for threading using C++11, I asked them to create a simple program called WordSearch that identifies possible Scrabble plays using a simple syntax. A single command-line argument is passed to the program — a template expression for searching through the dictionary. I had the students identify specific characters with the actual letter to be played, and the period character for places where any letter could be played. A typical run might look like this:
markn@ubuntu:~ $ ./WordSearch ..x..n Found 5 matches for ..x..n sextan sexton sixain taxman taxmen markn@ubuntu:~ $
The words are identified by brute force, working through all the entries in a copy of the Scrabble dictionary. (One of the nice things about using this pattern is that I can check the program output against grep, since the periods form a regular expression.)
To get started with the program, I asked the students to simply read the words from the scrabble dictionary into a simple deque<string>:
ifstream f( "sowpods.txt" );
if ( !f ) {
cerr << "Cannot open sowpods.txt in the current directory\n";
return -1;
}
string word;
deque<string> backlog;
while ( f >> word )
backlog.push_back( word );
I then asked them to create a function called find_matches that would locate all the matches in that deque, and return them to the caller in a vector<string>. A typical implementation might look like this:
vector<string> find_matches( string pattern, deque<string> &backlog )
{
vector<string> results;
while ( backlog.size() ) {
string word = backlog.front();
backlog.pop_front();
if ( match( pattern, word ) )
results.push_back( word );
}
return results;
}
The implementation of match() should be trivial.
Calling this routine and printing the results is easy enough now:
vector<string> words = find_matches( pattern, backlog );
cerr << "Found " << words.size()
<< " matches for " << pattern
<< endl;
for ( auto s : words )
cout << s << "\n";

