I have a struct in thread1. I pass the struct to thread 2. I want thread 1 to wait until thread 2 has modified the struct.
I have tried doing a while loop, which makes the thread sleep until the variable in the struct has changed:
while (MyStruct->variable== nullptr) {//do nothing}
however even after the variable has changed, the loop continues to sleep.
I think to make the while loop work properly, i would have to use an FThreadSafeBool. However this is not something UStructs can contain. What should I do in this situation?
I’m new to unreal, but in general, you need some kind of wait/notify mechanism.
In Unreal, I can see the FSemaphore class.
I am not sure from the docs how exactly it is supposed to be used, but generally, the gist is the waiting thread waits on that lock, and the thread that should provide the value should notify the lock when the value is ready, unblocking the waiting thread. But I am not sure if that’s the best solution for you.
This may well work. However this is blocking, right? It would be better if i could continue doing things on my extra thread, while waiting for the main thread to generate the data.
I have tried to do this using Tqueue, however i am having mixed success with that…
Yes, it will block the thread. If you want to do other work while one thread is waiting, there are two approaches: 1. Multiple threads, when one is waiting, another starts working. 2. Event loop, when thread is “waiting” it picks another task to work on in the meantime. Both are not easy to implement, so I would first check if unreal doesn’t have a ready to use solution. But, if you want to learn, then implementing this will teach you a lot about multithreading.
Are you wanting to block the main thread? That is to say, the game thread? If so, your game will completely freeze until you unblock the Game Thread.
Generally speaking, you would have the Game Thread kick off some work in another thread, with a bound delegate function which will be called automatically on the Game Thread when the work is complete. You achieve this in UE through the FRunnable class. However, if you are looking to simply block the Game Thread, you’ll need to look into the FCriticalSection type, which is UE’s version of a mutex, which is a special type of ‘lock’ used for thread synchronization. It works by blocking all threads that try to access the ‘lock’ while another thread has acquired it.
A really convenient way of using a mutex is through the concept of a Scoped Lock. We use this type of mutex by simply declaring a variable where ever we want to have our lock in effect. The lock will be owned by the thread until the variable goes out of scope.
A simple example:
void GameThread()
{
/*
* Doing some Game Thread stuff..
*/
// Location we want the thread to wait at..
// If we try to take ownership of this lock (Mutex)
// while ThreadTwo has ownership of it, then this
// thread will wait until it is free
FScopeLock ScopedLock(&Mutex);
/*
* Do things after Lock becomes available
*/
}
void ThreadTwo()
{
// Take ownership of the lock to block all other threads
FScopeLock ScopedLock(&Mutex);
/*
* Do protected work
*/
}
Also, an infinite while loop will heavily load the CPU and complete freeze the thread. You should never be implementing infinite while loops unless they contain a sleep. You can sleep threads using the Chrono and Thread libraries in the C++ Standard library. A simple example of that is this: