C++ Concurrency in Action Anthony Williams
Chapter 2. Managing Threads
2.1 Basic thread management
2.1.1 Launching a thread
If you don't wait for your thread to finish, then you need to ensure that the data accessed by the thread is valid until the thread has finished with it.
In particular, it is a bad idea to create a thread within a function that has access to the local variables in that function, unless the thread is guaranteed to finish before the function exits.
2.1.2 Waiting for a thread to complete
The act of calling join() also cleans up any storage assiciated with the thread, so the std::thread object is no longer associated with the now-finished thread.
2.1.3 Waiting in exceptional circumstances
The call to join() is liable to be skipped if an exception is thrown after the thread has been started but before the call to join().
2.1.4 Running threads in the background
Detached threads are often called daemon threads after the UNIX concept of a daemon process that runs in the background without any explicit user interface.
2.2 Passing arguments to a thread function
By default, the arguments are copied into internal storage, where they can be accessed by the newly created thread of execution, even if the corresponding parameter in the function is expecting a reference.
2.3 Transferring ownership of a thread
You must explicitly wait for a thread to complete or detach it before destruction.
2.4 Choosing the number of threads at runtime
2.5 Identifying threads
Chapter 3. Sharing data between threads