Refactor single-thread worker

Re-parallel Hull Update
Use new gap shaffle algorithm
This commit is contained in:
NotAlwaysTrue
2026-04-30 20:05:23 +08:00
parent 099d664731
commit 02689d0d86
6 changed files with 90 additions and 26 deletions
@@ -1,5 +1,9 @@
using System;
using Barotrauma.Networking;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using static Barotrauma.EosInterface.Ownership;
namespace Barotrauma
{
@@ -7,7 +11,13 @@ namespace Barotrauma
{
private ConcurrentQueue<Action> ActionQueue;
public static SingleThreadWorker GlobalWorker = new SingleThreadWorker();
public static SingleThreadWorker Instance = new SingleThreadWorker();
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly SemaphoreSlim actionSignal = new SemaphoreSlim(0);
private static Task WorkerTask;
public static readonly SemaphoreSlim SingleThreadActionStandbySignal = new SemaphoreSlim(1);
/// <summary>
/// Initilize a SingleThreadWorker
@@ -16,35 +26,75 @@ namespace Barotrauma
public SingleThreadWorker()
{
ActionQueue = new ConcurrentQueue<Action>();
WorkerTask = CreateProcessTask(cancellationTokenSource.Token);
}
public void Dispose()
{
cancellationTokenSource.Cancel();
WorkerTask.Wait();
WorkerTask.Dispose();
Instance = null;
cancellationTokenSource.Dispose();
actionSignal.Dispose();
SingleThreadActionStandbySignal.Dispose();
}
private async Task CreateProcessTask(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
try
{
await actionSignal.WaitAsync(100, token);
SingleThreadActionStandbySignal.Wait(CancellationToken.None);
RunActions();
}
catch (OperationCanceledException)
{
break;
}
finally
{
SingleThreadActionStandbySignal.Release();
}
}
}
/// <summary>
/// Add a pending action in a STW queue
/// Add a pending action in a STW queue.
/// DO NOT ABUSE IT OR IT WILL SLOW DOWN MAIN THREAD!!!!
/// </summary>
/// <param name="action"></param>
public void AddAction(Action action)
{
// enqueue and let background task handle the rest
ActionQueue.Enqueue(action);
if (actionSignal.CurrentCount == 0)
{
actionSignal.Release();
}
}
/// <summary>
/// Run all pending actions in the STW queue
/// </summary>
[STAThread]
public void RunActions()
private void RunActions()
{
while (ActionQueue.TryDequeue(out Action action))
{
try
{
action();
action.Invoke();
}
catch (Exception e)
{
// Just try-catch and do nothing but print errorlogs. We cannot afford crashing the game.
ConsoleColor originalForeground = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"WARNING: Error occurred when running Single Thread Actions. " +
Console.WriteLine($"WARNING: Error occurred when running Single Thread Actions." +
$"If the server didn't crash or stop responding then this should be fine \n{e}");
Console.ForegroundColor = Console.ForegroundColor;
}