A C++11 Threads Tutorial

Last week we created a simple program using the pthreads library. This week I’ve “translated” that program into the C++11 threads version, so you can see how it compares.

I say compares, but on linux, using GCC, the C++11 thread library is basically a wrapper for pthreads anyway, so although you are using native C++ commands, they are effectively calling the pthread commands that we saw last week.

So, the first thing to remember, when you are using the new C++11 thread library, is that you have to add a couple of flags to your build in order for it to run properly.

Firstly, you need to specify that we are using the latest standard, which you can do with:

-std=c++11

for gcc 4.7 onwards

or

-std=c++0x

for gcc 4.6.

Next you also need to compile with the -pthread flag. Yes, yes, it seems odd, but that’s just something gcc needs in order to be able to link everything up correctly.

So, our command to build, for the program I’ll show you below, will be:

g++ -Wall threadsc11.cpp -pthread -std=c++11

Note that if you don’t include the -pthread flag, you will get an error along the lines of this when you try to RUN (not link) your program:

terminate called after throwing an instance of 'std::system_error'.
Enable multithreading to use std::thread: Operation not permitted.

Right, now let’s look at the code in the threadsc11.cpp file, and then we’ll have a chat about it.

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <vector>

using namespace std;

#define NUM_THREADS 5

#define BLACK   "\033[0m"
#define RED     "\033[1;31m"
#define GREEN   "\033[1;32m"
#define YELLOW  "\033[1;33m"
#define BLUE    "\033[1;34m"
#define CYAN    "\033[1;36m"

std::mutex colour_mutex;

void PrintAsciiText(int id)
{
    string colour;

    colour_mutex.lock();
    switch(id)
    {
    case 0:
        colour = RED;
        break;
    case 1:
        colour = GREEN;
        break;
    case 2:
        colour = YELLOW;
        break;
    case 3:
        colour = BLUE;
        break;
    case 4:
        colour = CYAN;
        break;
    default:
        colour = BLACK;
        break;
    }

    cout << colour << "I'm a new thread, I'm number " << id << BLACK << endl;
    colour_mutex.unlock();
}

int main()
{
    vector<thread> threads;

    for(int i = 0; i < NUM_THREADS; ++i)
    {
        threads.push_back(std::thread(PrintAsciiText, i));
    }

    for (vector<thread>::iterator it = threads.begin() ; it != threads.end() ; ++it)
    {
        it->join();
    }

    return 0;
}

Looking at the main function: firstly, I’ve used a vector to store the threads in, instead of an array of ints (which is what the previous pthread_create call returned). I’m not storing ints in this version, I’m storing the type “thread”, which is our new C++11 thread type.

Next, I have the same for loop, and I’m creating a new thread each time using std::thread. In brackets after the call come two arguments. The first is the sub-routine that the thread will execute, and the second is a parameter to pass to that sub-routine. The second parameter is entirely optional. I could have just called a sub-routine and not passed in the number, in which case there would only have been one argument in the brackets – the name of the sub-routine).

Finally, after creating all those threads, I iterate through the vector and call the C++11 join() call for each thread. This avoids the program ending before all of our threads have finished doing there work, as discussed last week.

In the subroutine, I use the same code, and a lock in the same place, but this time it’s using the C++11 mutex class (note it requires an additional header at the top). I also have to change the name of my mutex from “mutex” to “colour_mutex” so that it doesn’t clash with the in-built mutex class.

Note that I no longer need the pthread_exit calls in the sub-routine, as the C++11 library takes care of that. Notice also that the sub-routine is a standard function that returns void, and it takes an int parameter (not a pointer), whereas with last week’s pthread tutorial I had to create a function that returned a void* and the argument had to be passed as a void *.

Last of all, let’s see what the output looks like:

c11threads

I’ll leave it up to you to experiment with what happens if you don’t use the mutex and the join calls (as we did last week).