Pass a temporary object as a thread parameter

Example:

#include <iostream>
#include <thread>

void myprint(const int &i, char *pmybuf) {
	std::cout << "i = " << i << std::endl;
    std::cout << "pmybuf = " << pmybuf << std::endl;
	return;
}

int main(a)
{
	int my = 1;
	int &may = my;
	char buf[] = "I love china";

	std::thread obj(myprint, my, buf);
	obj.join(a); std::cout <<"main thread finished!!" << std::endl;
	return 0;
}
Copy the code

Pitfalls to avoid

  • If the thread detach from the main thread, I is not a true reference to my, but is actually passed (copied). It is still safe for the child thread to use I even after the main thread has finished running, but passing references is still not recommended.

If you use the function directly, the address of I is the same as the address of the argument passed in.

  • Pmybuf still refers to the original string, so it’s not safe to write this and it’s definitely a problem when detach.
  • Ex. :

Parameters of my

0x00EFF940 {1} 0x00EFF940 {1} directly passed in function 0x00EFF940 {1} using thread 0x01010a9c {1}Copy the code

Parameter buf

0x00b7f750 "I love china"The function is passed 0x00b7f750"I love china"
&pmybuf
0x00b7f65c {0x00b7f750 "I love china"0 x00b7f750} thread"I love china"
&pmybuf
0x00cef99c {0x00b7f750 "I love china"}
Copy the code

Pitfalls to avoid 2

  • When buf is converted to string, there is a possibility that mybuf will not be converted to string until mybuf has been reclaimed (main has been executed).

  • MyThread (myPrint, mvar, string(mybuf))); It would be perfectly safe…

The copy constructor is called with this method, which creates a temporary object, and a temporary object is generated.

#include <iostream>
#include <thread>
#include <string>
using namespace std;

void myPrint(const int i, const string& pmybuf)
{
	cout << i << endl;
	cout << pmybuf << endl;
}

int main(a)
{
	int mvar = 1;
	int& mvary = mvar;
	char mybuf[] = "this is a test";
	// If detach is done, this is still not secure
	Mybuf was reclaimed because the main thread ran out. Mybuf was implicitly converted to string
	Thread myThread(myPrint, mvar, string(mybuf)); It would be perfectly safe...
	thread myThread(myPrint, mvar, mybuf);
	myThread.join(a);//myThread.detach();

	cout << "Hello World!" << endl;
}
Copy the code

Fact 1: Just pass A temporarily constructed class A object to the thread as an argument. It must be possible to build the second argument to the thread function before the main thread completes, thus ensuring that even the Detach child threads run safely.

3. Summary

  • If you pass a simple parameter like int, it is recommended that you pass it by value instead of by reference.
  • If you pass class objects, avoid implicit type conversions, just build temporary objects on the thread creation line, and then in the function argument, use references, otherwise create an object;
  • It is recommended to use join() instead of detach() : then there is no problem with invalid local variables causing threads to reference memory illegally;

Temporary objects as thread parameters continue

1. Thread ID concept

  • An ID is a number, and each thread (whether primary or child) actually has a number, and that number is different for each thread
  • The thread id can be obtained using a function in the C++ standard library. STD: : this_thread: : get_id () to obtain

2. Temporary object construction timing capture if using implicit type conversion:

std::thread myobj(myprint,mvar);
Copy the code

Fatal problem: constructing class A objects in child threads

If you use the temporary object method

std::thread myobj(myprint,A(mvar));
Copy the code

After temporary objects are used, all class A objects are already built in the main() function

Pass smart Pointers to class objects as thread parameters

1

#include <iostream>
#include <thread>
using namespace std;

class A {
public:
	mutable int m_i; //m_i can be modified even if it is const
	A(int i) :m_i(i) {}
};

void myPrint(const A& pmybuf)
{
	pmybuf.m_i = 199;
	cout << "The parameter address of the child thread myPrint is" << &pmybuf << "thread = " << std::this_thread::get_id() << endl;
}

int main(a)
{
	A myObj(10);
	// the reference in myPrint(const A& pmybuf) cannot be removed, if removed, an additional object will be created
	// Const cannot be removed as it would be an error
	// The copy constructor is called in the child thread to construct a new object, even if a const reference is passed.
	// So changing m_i in the child thread does not affect the main thread
	Thread myThread(myPrint, STD ::ref(myObj));
	Const = myPrint; const = myPrint; const = myPrint; const = myPrint
	thread myThread(myPrint, myObj);
	myThread.join(a);//myThread.detach();

	cout << "Hello World!" << endl;
}
Copy the code
  • The reference in myPrint(const A& pmybuf) cannot be removed because removing it will create an additional object
  • Const can’t be removed, it’s an error
  • Even if a const reference is passed, the copy constructor is called to construct a new object in the child thread, so changing the value of m_i in the child thread does not affect the main thread
  • Thread myThread(myPrint, STD ::ref(myObj));
  • Const = myPrint; const = myPrint; const = myPrint

STD ::ref() can pass a true reference to a function

2

#include <iostream>
#include <thread>
#include <memory>
using namespace std;

void myPrint(unique_ptr<int> ptn)
{
	cout << "thread = " << std::this_thread::get_id() << endl;
}

int main(a)
{
	unique_ptr<int> up(new int(10));
	// Exclusive Pointers can only be passed to another pointer by STD ::move()
	// After passing, up points to empty, and the new PTN points to the old memory
	// Detach cannot be used at this point because if the main thread finishes first, the object pointed to by PTN is released
	thread myThread(myPrint, std::move(up));// Since move is used here, the previous up value does not exist, and the child function will be released when it finishes executing
	myThread.join(a);//myThread.detach();

	return 0;
}
Copy the code
  • Exclusive Pointers can only be passed to another pointer by STD ::move()
  • After passing, up points to empty, and the new PTN points to the old memory
  • So you can’t use detach at this point because if the main thread finishes first, the object pointed to by PTN is released

Use member function Pointers to thread functions