Correct way of passing pointer to another thread
How do you run func1() and func2() under different threads? func1() directly calls func2(), so they run under the same thread. Even the first implementation of func1() should work, as the array is still in its place.
EDIT:
But calling func2() directly from within func1() isn't an "asynchronous call to func2()" (even if at some other point it's used as a thread function). "Asynchronous call" means creating a new thread with func2() as the thread function. If so, this behaviour is very much expected, because func1() may have exited when func2() runs, and the array wouldn't exist by that time. On the other hand, the heap-block would still be allocated, so this would work. func2() should release the block then.
EDIT2:
Ummm, yes, the 2nd version is indeed an "asynchronous call to func2()", so the objects' lifetime considerations listed above indeed apply.
Pass pointer to on-stack variable for new thread - is this code safe?
Is that a real concern?
Yes. Its not a safe way of doing it.
You can pass the value directly instead of passing its address.
pthread_create(&client_thread, NULL, echo_data, (void*) incoming_client_socket);`
and the thread function should be like
void* echo_data(void* client_socket) {
int socket = (int)client_socket;
/* your code */
}
If you wish to pass more than one elements to the thread, then you could wrap it inside a structure, create a structure pointer for it, allocate memory and fill the values and pass the pointer to the threads.
struct X {
int socket;
/* other members here*/
};
and
while (1) {
int incoming_client_socket = wait_for_connection(server_socket);
fprintf(stdout, "new connection accepted...\n");
struct X *ptr = malloc (sizeof(struct X));
ptr->socket = incoming_client_socket;
/* other assignment here */
pthread_create(&client_thread, NULL, echo_data, (void*)ptr);
}
And your thread func should look like
void* echo_data(void* client_socket) {
// for the sake of argument - suppose there's a lot of code here before we copy the socket to local variable:
struct X *ptr = (struct X *)client_socket;
// send back whatever is coming from client
return (void*)0;
}
Don't forget to free the memory.
Passing pointer to a member function to a seperate thread
PostMessage is not a great way to marshall function pointers and work work items between threads. You're better off just inventing your own thread-safe data structure and queuing work items to the the render thread.
But if you are really bent on passing a function using PostMessage... then std::function
combo'd with a lambda could work.
Declare this in a common header file:
struct MyCustomMessage
{
std::function<void()> fn;
};
From the ViewPortController thread, do this to "send" the function invocation to the other thread.
MyCustomMessage *pMsg = new MyCustomMessage();
pMsg->fn = [this](){
this->DrawSomeStuff();
};
PostThreadMessage(uiThreadID, UWM_DRAW, 0, reinterpret_cast<LPARAM>(pMsg);
In the other thread:
ThreadController::draw(WPARAM wParam, LPARAM lParam) {
MyCustomMessage* pMsg = reinterpret_cast<MyCustomMessage*>(lParam);
pMsg->fn();
delete pMsg;
}
Passing pointer as argument with std::thread function C++11
The immediate problem which triggers compilation error is right here:
void checkMin(int value);
This is the prototype of your function, and it is incorrect - it should be
void checkMin(int* value); //<-- not the pointer.
But this is not the only one! Your code makes no sense. Look at this fragment:
std::thread tabThreads[threadCount];
std::thread *ptrTabThreads = tabThreads;
for (int i = 0; i < threadCount; ++i) {
ptrTabThreads = new std::thread(checkMin, ptrTab[i]);
ptrTabThreads->join();
++ptrTabThreads;
}
What's the purpose of all this jumping with pointers? You also have a leak in your code, since you are modifying the pointer you obtained from new
before delete
ing it. Why not use following simple code?
std::array<std::thread, threadCount> tabThreads;
for (int i = 0; i < threadCount; ++i) {
tabThreads[i] = std::thread(checkMin, ptrTab[i]);
tabThreads[i].join();
}
This still serves no pratical purpose (application remains effectively single-threaded, since you join your thread right after creating it), but at least, the code is correct. To really do some fancy multithreading, you need your loop to look like following:
for (int i = 0; i < threadCount; ++i)
tabThreads[i] = std::thread(checkMin, ptrTab[i]);
for (std::thread& t : tabThreads) // so-called range-for loop. Nice thing!
t.join();
This will paralellize stuff!
Instantiating a pointer and passing it to two Queues to be consumed by two Threads?
Does that mean that the object only gets deleted when it gets pulled out of both of the threads reading from this queue and then only the data_ptr memory allocated gets deleted?
No it doesn't. The first use of std::move
will 'rob' data_ptr
and the second is, effectively, UB.
Don't be afraid to copy a std::shared_ptr
. It is a cheap operation and doesn't copy the underlying data. In fact, that is the whole idea behind std::shared_ptr
- to share ownership of whatever it points to, with the object being deleted when the last shared_ptr
goes out of scope.
If you're desparately worried about performace (which I am not) then you could pass data_ptr
to data_queue_.write
by value (thus making a copy) and to custom_queue_.write
by reference (thus not making a copy). In neither case is std::move
appropriate or useful.
But code like this is fragile. I strongly recommend you keep things simple and pass data_ptr
by value in both cases. This is how shared_ptr
is meant to be used. People don't talk about modern C++ having value semantics for nothing.
When is passing a pointer to another thread in C++11 a race condition?
No in both cases.
The first example would in principle be a definite race condition if it wasn't for some special properties of std::thread
.
The compiler is in principle allowed to reorder moves, however constructing a thread object has sequential consistency, which formally guarantees that it works. But even if it didn't have that property, creating and starting a thread in practice takes a very considerable time (hundred thousands to millions of times as long as executing a few move instructions) so you would practically (not formally, but practically) be guaranteed that there is no race, even if there was no sequential consistency (this "practical guarantee" is admittedly somewhat disputable, it might not hold true in contrieved extreme cases, but the formal guarantee is true either way).
The second example uses a concurrent queue, which by definition is engineered (either using a lock or using a lockfree algorithm) in such a manner that no race condition occurs.1
In either case, the pointer that ends up being in the queue is guaranteed to be either not there at all (in which case the pop
operation will block or fail, where "fail" means that the consuming thread knows that there is no valid pointer available at this time -- it will not assume some invalid value) or it is there in a valid state.
The atomic (locked or lock-free) operation that adds the pointer to the queue guarantees that the object construction which happened before is also realized before (i.e. no pointer on queue without valid object).
This implies that the object must also be valid when its pointer is retrieved from the queue (unless you cheat).
1This obviously assumes correct operation of the queue, but that's a fair assumption.
Passing Custom Class Pointer to Another Thread via signal/slot mechanism in Qt
I've found the solution, thanks To @G.M
We need to register the type exactly how we are going to use it, such as:
qRegisterMetaType<std::shared_ptr<ITradeMessage>>()
Related Topics
Fastest Way to Check If a File Exists Using Standard C++/C++11,14,17/C
How to Split an Int into Its Digits
Invalid Operands Error for Addition and Integer Division
How to Align Text to the Right Using Cout
C++ High Performance File Reading and Writing (C++14)
Vector of Structs Initialization
Checking the Neighbour Values of Arrays
Method That Converts Uint8_T to String
Writing a Sequence of Numbers Like: 1 22 333 4444 55555
How to Read in User Entered Comma Separated Integers
How to Fill 2D Array With the User'S Input
Automatically Refreshing a Qtableview When Data Changed
When Should Static_Cast, Dynamic_Cast, Const_Cast, and Reinterpret_Cast Be Used
How to Test Whether Stringstream Operator≫≫ Has Parsed a Bad Type and Skip It
How Does Guaranteed Copy Elision Work
Returning Multiple Values from a C++ Function
Exotic Architectures the Standards Committees Care About
Array Size At Run Time Without Dynamic Allocation Is Allowed