Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
C++11 multithreading tutorial (solarianprogrammer.com)
56 points by g3orge on Dec 16, 2011 | hide | past | favorite | 16 comments


Multithreaded programming in C++11 is pretty convenient. std::thread, together with std::chrono are very good threading and timing libraries. The only thing better than that is using native API's like pthreads + posix clocks.

Here's an example: C++11 has timed wait on mutex and condition variables, using std::chrono time stamps for absolute and relative times. Most threading wrappers don't provide this but it's available in pthreads (and I guess Windows API too). Not only does C++11 provide this but it plays along very nicely with the clocks in chrono and you can use it with different time sources, like the monotonic system clock.

I've used both when building multithreaded "main loops" for game/simulation purposes. Using C++11 threads + chrono is a lot nicer to the programmer than doing the same with posix pthreads in C. The biggest improvement is exception safety, type safety and rich types for clocks and timestamps come second.


It's pedantry, but pthreads isn't "native" anywhere either. It's a standardized API on top of lower level primitives (in Linux, clone() and futex() basically).


This kind of threaded for-loop processing is precisely what OpenMP is designed to take care of without having to control threads directly from your code. Making sure your code is thread-safe is good practice anyway, and running the for loop in parallel could be as easy as using:

  #pragma omp for ...
Disclaimer: I haven't found that OpenMP is too useful outside of pure computation, but it is worth mentioning if all you want to do is run loops in parallel.

Current spec (pdf): http://openmp.org/mp-documents/OpenMP3.1-CCard.pdf


Lots of good posts there. Very mixed reviews on Amazon(.co.uk) of the book he recommends tho'[1] has anyone else got any opinions on it?

[1] http://solarianprogrammer.com/2011/10/07/great-book-about-c1...


Not directly, but the few Wrox books I've read made such a negative impression on me that I won't buy their books any more.

One of the Amazon one-star reviews says, "For a book of this size, I would have expected extensive coverage of key C++ concepts. However, I am very unsatisfied with this book, since the coverage of C++ is superficial at best."

Sounds exactly like a Wrox book.


It is a good book if you already know C++ and you want to get up to speed with the new C++11 standard. Not recommended for beginners in C++.

For the definitive reference I would wait for the 4th edition of "The C++ Programming Language" by B. Stroustroup.


I couldn't find a way to control affinity with the C++11 thread feature. That seems like a good reason to stick with pthread.


How to improve this tutorial:

- Use lambdas

- Use std::scoped_ptr or std::shared_ptr

- Use std::vector instead of C Array

- Use references instead of pointers

That would prevent unnecessary pitfalls.


Agreed. But, see this comment in the source: //It may seem strange to not use a vector here, however (at the time of this writing) clang++ doesn't let you use a vector to store a group of threads

AFAIK, it should be possible to put threads (non-copyable but movable) to a vector in C++11. Of course, then the vector will not be copyable (but it will be movable). I think I've even done it, but I used GCC, which has had pretty good C++11 support for quite a while now. (sorry, I'm too lazy to verify)


I'm not sure it works even if it's moveable because there's no guarantee it will make copy elision everywhere it's needed.

One way I was thinking about it was std::vector<std::shared_ptr<std::thread>>

Additionally, this sucks:

#define NUM_THREADS 10

In C++03 you can write

static const int num_threads = 10;

Which is much better.

And instead of:

for(int i=0;i<NUM_THREADS;i++){ t[i] = thread(call_from_thread,i); }

Better use std::generate.

I may look like I'm nitpicking but I think it's paramount in a tutorial to have all details really, really right so that it may trigger other questions and go in depth about why things are better a way or the other.


>> I'm not sure it works even if it's moveable because there's no guarantee it will make copy elision everywhere it's needed.

Of course it works, since std::thread is movable but non-copyable, std::vector<std::thread> will be movable but non-copyable too. So the compiler type checking will make sure it's not copied anywhere.

This works like a charm (with GCC 4.7-ish from git):

  #include <thread>
  #include <vector>
  #include <iostream>
  #include <algorithm>

  int main()
  {
      std::vector<std::thread> threads;

      for(int i = 0 ; i < 10 ; ++i)
          threads.push_back(std::thread([=]() { std::cout << i << std::endl; }));

      std::for_each(threads.begin(), threads.end(), [](std::thread& thread) { thread.join(); });
  }
>> Better use std::generate.

I used to nitpick about not using std::algorithms when they're available, but I grew out of it. I figured out that std::algos are very limited (esp. in c++98), and while you can use them to do stuff, it usually takes a significant amount of brainpower only to reformulate your problem to be suitable for std::algorithms. There are so many situations where a good old loop will produce more readable code faster, so why bother with the standard algorithms if they're not a perfect fit?

Btw. has std::generate improved at all in C++11? It's one of the most limited algorithms in c++98.


>> it usually takes a significant amount of brainpower only to reformulate your problem to be suitable for std::algorithms

That's true, but the final result generally ends up with less bugs and better thought out algorithms. It forces you to think "what problem am I currently trying to solve?"


I don't have much experience with clang, but there are still better ways to express a list of threads:

    - thread t[NUM_THREADS]; // since NUM_THREADS is constant
    - std::unique_ptr<thread[]> t(new thread[NUM_THREADS])


Same goes for lambdas, clang++ has no support for lambdas.


> - Use std::vector instead of C Array

What about std::array?


It will work with std::array.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: