Hey (this is my first post), i am tesing some multithreading in unreal engine with the help of Ramas Tutorial about multithreading and was asking myself how synchronization would work with the unreal engine thread classes.
So, i was trying to use FCriticalSection… but i don’t get it work properly… FCriticalSection::TryLock() alwas returns false after it was unlocked from the destructor of FScopeLock.
What am I doing? I create 2 instances of the class below if i press a button in the game. Thread 1 does his work immediately (calculating some prime numbers and stop thread 2 from doing the same) and thread 2 waits for an unlocked FCriticalSection but stucks in his wait loop forever. NOW, why is going to be an infinite loop? I also tried it with 2 threads inside 1 instance of the class and with FCriticalSection as member variable instead of a static class variable - but without any changes.
That’s the class I’m working with:
.H FILE:
class FExampleThreadWorker : public FRunnable
{
public:
FExampleThreadWorker();
~FExampleThreadWorker();
//Begin FRunnable Methods
bool Init() override;
uint32 Run() override;
void Stop() override;
//End
protected:
/** Thread to run the worker FRunnable on */
FRunnableThread* Thread;
static FCriticalSection critical;
int workerNumber;
static int workerCount;
};
.CPP FILE
int FExampleThreadWorker::workerCount = 0;
FCriticalSection FExampleThreadWorker::critical;
FExampleThreadWorker::FExampleThreadWorker()
{
workerNumber = ++workerCount;
FString name("FExampleThreadWorker");
name.AppendInt(workerNumber);
Thread = FRunnableThread::Create(this, *name, 0, TPri_Normal);
if (!Thread)
GLog->Log("Failed to create FExampleThreadWorker Thread!");
}
FExampleThreadWorker::~FExampleThreadWorker()
{
delete Thread;
Thread = nullptr;
--workerCount;
}
bool FExampleThreadWorker::Init()
{
return true;
}
uint32 FExampleThreadWorker::Run()
{
//Initial wait before starting
FPlatformProcess::Sleep(0.03f);
//wait until unlocked
while (!critical.TryLock());
//locked scope
{
FScopeLock lock(&critical);
GLog->Log("Thread " + FString::FromInt(workerNumber) + " start locked work");
//some prime number calculation
int32 TestPrime = 2;
int32 primesFoundCount = 0;
bool NumIsPrime = false;
while (primesFoundCount <= 20000)
{
NumIsPrime = true;
TestPrime++;
for (int32 b = 2; b < TestPrime; b++)
{
if (TestPrime % b == 0)
{
NumIsPrime = false;
break;
}
}
if (NumIsPrime)
++primesFoundCount;
}
GLog->Log("Thread " + FString::FromInt(workerNumber) + " finished locked work");
}
return 0;
}
void FExampleThreadWorker::Stop() { }
Maybe there’s another and easier way of doing this… I hope anyone can help me with this issue or suggest a better solution for thread synchronization in unreal engine.
Thanks in advance for your help!
Bernhard