# Chapter 2 Managing Threads ## Disclaimer This is my personal notes of the [C++ Concurrency in Action, Second Edition](https://www.manning.com/books/c-plus-plus-concurrency-in-action-second-edition) book. Most ideas come from the book. ## Basic Usage Normally, we start a thread in C++ by `std::thread(work_func, arg1)` and then wait for it to complete with `join`. If we don't call `join`, the main thread will complete before the `t` thread, and `t` will be handled by OS. The example below also shows how to pass arguments to thread by value. The integer `num` is **copied** to the thread's own address space. ```C++ #include <thread> #include <iostream> void work_func(int num) { std::cout << "Intensive work " << num << std::endl; } int main() { std::thread t(work_func, 10); t.join(); } ``` If we don't want to wait for the thread to finish, we can call `detach`. Then, the thread will be classified as daemon thread, which typically run long-time background work. ```C++ #include <thread> #include <iostream> void work_func(int num) { std::cout << "Intensive work " << num << std::endl; } int main() { std::thread t(work_func, 10); // t.join(); t.detach(); } ``` ## Pass reference to thread Suppose the worker function requires reference as arguments, we would need `std::ref` to accomplish this. In following example, we use assert to check if the number is correctly incremented. ```C++ #include <thread> #include <cassert> void work_func(int& num) { num++; } int main() { int local = 10; std::thread t(work_func, std::ref(local)); // std::thread t(work_func, local); <-- will throw error t.join(); assert(local == 11); } ``` ## Move data to thread If the arguments can only be **moved** but not **copied**, we need to use `std::move` to move the object to the thread's local storage. The following example also shows that we can use `std::this_trhread::get_id()` to get the thread id. It is useful for us to identify thread when we manages threads with `std::vector<std::thread>`. ```C++ #include <thread> void work_func(std::unique_ptr<int> num_ptr) { (*num_ptr)++; std::cout << "Thread: " << std::this_thread::get_id() << ", Value: " << *num_ptr << std::endl; } int main() { std::unique_ptr<int> local = std::make_unique<int>(10); std::thread t(work_func, std::move(local)); t.join(); } ``` ## Use with member function The first argument of `std::thread` will be the **reference** to the class's method. Note that for non-member function, we do not need to explicitly pass reference to function to `std::thread`. The second argument is the object pointer, where the memeber function will be called on this object. The later arguments will be the arguments of the member function. ```C++ #include <thread> #include <cassert> class Worker { public: void work_func(int& num) { num++; } }; int main() { int local = 10; Worker w; std::thread t(&Worker::work_func, w, std::ref(local)); t.join(); assert(local == 11); } ``` ## Follow-up reading in this chapter - `joining_thread` with **RAII**(Resource Acquisition Is Initialization) - naive parallel version of `std::accumulate` ## About Me A self-motivated programmer who is exploring low-latency C++. >Personal Website: https://jacky-chen-portfolio.vercel.app/ >GitHub: https://github.com/TypeErrorEngine2022 >Email: jackychenworkcontact@gmail.com