Threads using C++11 in 5 Minutes

Threads are seen as scary and strange. If used incorrectly, they can be frustrating and appear inconsistent. The good news is that C++11 has a great threading model and still links with useful libraries so you can get work done.

Minimum to Use std::thread

To use threads, you must know a little bit about how function pointers work in C++, because function pointers are how you specify the work to do in the thread. These function pointers specify what is known as the work function. At a minimum, your program also needs:
[table-wrap bordered=”true” striped=”true”]

What Why
#include Class declaration
void workFunc(); Declaration of thread work function
std::thread t1(&workFunc); Thread instance
t1.join(); Wait for thread to finish and clean up
[/table-wrap]

Starting Threads with “Regular” Functions

Function pointers for “regular” functions, also known as file-scope functions, work pretty much like you’d expect: take the address of the function name and then provide the arguments like you would if calling the function.

Note that you can also get by without explicitly taking the address, like std::thread t1(printHello,name);. This also works for static member functions, but it does not work with (non-static) member functions. So, for consistency, we will take the addresses of all work functions.

Starting Threads with Static Member Functions

In both the case of a file scope function and a static member function, the function pointer does not depend on a class instance. Given the semantic similarity of file scope functions and static member functions, they (unsurprisingly) use similar syntax when specifying a thread work function.

Launching a Thread with a Member Function

Member functions are fundamentally different from file scope and static member functions because member functions access member data in a particular instance of a class. Member function pointers are a different type from pointers to file scope functions and static member functions. They are usually larger, sometimes much larger. It is not uncommon for a member function pointer to be twice the size of a file scope function pointer. This is because the member function pointer must store both a function pointer and a pointer to the member data associated with the instance.

Whenever you invoke a member function pointer, the first argument must be an instance pointer of the appropriate type.

Putting It All Together

Here, we show the whole program followed by its output. The above fragments do not compile.

Wrap-up

There is likely less complexity involved than you expected when using threads. Things do get more involved when data structures are shared, but by using RAII along with destructors to handle “atypical” situations, C++11 threads are remarkably usable.

Leave a Reply