Make entity lists thread-safe with copy-on-write wrappers

Replaced static entity lists (e.g., HullList, GapList, MapEntityList, etc.) with thread-safe copy-on-write wrappers to improve concurrency and prevent race conditions. Updated usages and related methods to support the new thread-safe collections, ensuring atomic operations and lock-free reads throughout the codebase.
This commit is contained in:
Eero
2025-12-28 21:59:03 +08:00
parent bd1e624eb1
commit e167a34f32
13 changed files with 613 additions and 68 deletions
@@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using Barotrauma.IO;
@@ -20,10 +21,10 @@ namespace Barotrauma
public const ushort MaxEntityCount = ushort.MaxValue - 4; //ushort.MaxValue - 4 because the 4 values above are reserved values
private static readonly Dictionary<ushort, Entity> dictionary = new Dictionary<ushort, Entity>();
private static readonly ConcurrentDictionary<ushort, Entity> dictionary = new ConcurrentDictionary<ushort, Entity>();
public static IReadOnlyCollection<Entity> GetEntities()
{
return dictionary.Values;
return (IReadOnlyCollection<Entity>)dictionary.Values;
}
public static int EntityCount => dictionary.Count;
@@ -122,13 +123,11 @@ namespace Barotrauma
//give a unique ID
ID = DetermineID(id, submarine);
if (dictionary.ContainsKey(ID))
if (!dictionary.TryAdd(ID, this))
{
throw new Exception($"ID {ID} is taken by {dictionary[ID]}");
}
dictionary.Add(ID, this);
CreationStackTrace = "";
#if DEBUG
var st = new StackTrace(skipFrames: 2, fNeedFileInfo: true);
@@ -324,7 +323,7 @@ namespace Barotrauma
}
else
{
dictionary.Remove(ID);
dictionary.TryRemove(ID, out _);
}
IdFreed = true;
}