FCriticalSection not working reliably?

MaxPower42
Thu, 11 May 2023 12:24:53 +0000
Programming & Scripting

I am new to multi-threading. I am trying to reserve sectors of voxels being worked on for one Task/Thread at a time by using an FCriticalSection (aka Mutex) as a private member of each sector. I made sure it can only be accessed through these simple functions, so I can monitor their use:

void AVoxelSector::Lock(FVoxelTaskBase* Task)
{
	Mutex.Lock();

	bool error = (bool)ActiveTask;

	if (error)
		DEBUG_Log.Add(FString::Printf(TEXT("Sector %s locked AGAIN by %s  -  WAS LOCKED BY %s"), *SectorCoords.ToString(), Task ? *Task->Name : L"NULL", *ActiveTask->Name));
	else
		DEBUG_Log.Add(FString::Printf(TEXT("Sector %s locked by %s"), *SectorCoords.ToString(), Task ? *Task->Name : L"NULL"));

	ActiveTask = Task;
}
void AVoxelSector::Unlock()
{
	DEBUG_Log.Add(FString::Printf(TEXT("Sector %s unlocked from %s"), *SectorCoords.ToString(), ActiveTask ? *ActiveTask->Name : L"NULL"));

	ActiveTask = NULL;
	Mutex.Unlock();
}

The Tasks are derived from FNonAbadonableTask and run from the main thread via lambda-function using Async() like this:

Async(EAsyncExecution::ThreadPool, [UpdateBorderTask]()
{
	UpdateBorderTask->Run();
});

I was under the impression that, using a mutex, I could rely on threads waiting in line and never locking at the same time, but every now and again a task will simply lock my sector, while another task is still working on it. I checked everything. There must be something I am missing… Any help?

I think it might be the same thread locking the mutex again after finishing one Task and starting the next, but is it supposed to work like that?? Finishing the Task is not supposed to unlock the mutex, because there is still some work to be done afterwards by the main thread, which then eventually unlocks the mutex.

1 post - 1 participant