Thread
Std: thread indicates an executable thread, which must contain the header file <thread>. Std: thread can be used together with a common function, an anonymous function, and a class that implements the operator () function. In addition, it allows passing any number of parameters to the thread function.
- #include <thread>
-
- void func()
- {
- // do some work
- }
-
- int main()
- {
- std::thread t(func);
- t.join();
-
- return 0;
- }
In the above example, t is a thread object, and the function func () runs in this thread. The call to the join () function will keep the calling thread in this example the main thread) in the blocking state until the execution of the thread t is completed. If a thread function returns a value, the value is ignored. However, this function can receive any number of parameters.
- void func(int i, double d, const std::string& s)
- {
- std::cout << i << ", " << d << ", " << s << std::endl;
- }
-
- int main()
- {
- std::thread t(func, 1, 12.50, "sample");
- t.join();
-
- return 0;
- }
Although any number of parameters can be passed to the thread function, all parameters should be passed by value. If you want to pass parameters by reference, you must encapsulate the Parameters Using std: ref or std: cref as shown in the following example.
- void func(int& a)
- {
- a++;
- }
-
- int main()
- {
- int a = 42;
- std::thread t(func, std::ref(a));
- t.join();
-
- std::cout << a << std::endl;
-
- return 0;
- }
The program prints 43 results, but if std: ref is not used to encapsulate parameter a, the output result is 42.
In addition to the join method, this thread class also provides two other methods:
Swap: swap the underlying handles of two thread objects.
Detach: allows the thread that executes this method to separate itself from its thread object. The detached threads are no longer associated with threads, and you cannot wait for them to end ).
- int main()
- {
- std::thread t(funct);
- t.detach();
-
- return 0;
- }
It is very important that if a thread function throws an exception, the exception cannot be caught using the conventional try-catch statement. In other words, the following practices are not feasible:
- try
- {
- std::thread t1(func);
- std::thread t2(func);
-
- t1.join();
- t2.join();
- }
- catch(const std::exception& ex)
- {
- std::cout << ex.what() << std::endl;
- }
To pass exceptions between threads, You need to capture them in the thread functions and store them in a suitable place, which is easier for other threads to subsequently obtain these exceptions.
- std::mutex g_mutex;
- std::vector<std::exception_ptr> g_exceptions;
-
- void throw_function()
- {
- throw std::exception("something wrong happened");
- }
-
- void func()
- {
- try
- {
- throw_function();
- }
- catch(...)
- {
- std::lock_guard<std::mutex> lock(g_mutex);
- g_exceptions.push_back(std::current_exception());
- }
- }
-
- int main()
- {
- g_exceptions.clear();
-
- std::thread t(func);
- t.join();
-
- for(auto& e : g_exceptions)
- {
- try
- {
- if(e != nullptr)
- {
- std::rethrow_exception(e);
- }
- }
- catch(const std::exception& e)
- {
- std::cout << e.what() << std::endl;
- }
- }
-
- return 0;
- }
To learn more about capturing and passing exceptions, read these two books.Handle the C ++ exception thrown by the auxiliary thread in the main threadAndHow to transmit exceptions between threads.
Before learning deeply, note that the header file & lt; thread & gt; provides some help functions in the namespace std: this_thread:
- Get_id: returns the id of the current thread.
- Yield: When waiting, the scheduler can run other available threads first.
- Sleep_for: blocks the current thread at a time not less than the time specified by its parameter.
- Sleep_util: keeps the current thread in the blocking state until the specified time of the parameter reaches.