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.
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."
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 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?"
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.