From bd1e624eb1fbcc7e157d18005f49893cda1a0d52 Mon Sep 17 00:00:00 2001 From: Eero Date: Sun, 28 Dec 2025 17:45:51 +0800 Subject: [PATCH] Remove unnecessary thread-safety code from entity spawning Eliminated redundant locks and related comments in EntitySpawner and Entity classes, simplifying the spawn and remove queue handling. Also removed outdated comments in GameScreen regarding thread safety. These changes assume entity spawning and removal are no longer performed from multiple threads, improving code clarity and maintainability. --- .../SharedSource/Map/Entity.cs | 1 - .../SharedSource/Networking/EntitySpawner.cs | 95 +++++-------------- .../SharedSource/Screens/GameScreen.cs | 2 - 3 files changed, 26 insertions(+), 72 deletions(-) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Entity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Entity.cs index d9665886e..54b5014d0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Entity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Entity.cs @@ -147,7 +147,6 @@ namespace Barotrauma CreationStackTrace += $"{fileName}@{fileLineNumber}; "; } #endif - #warning TODO: consider removing this mutex, entity creation probably shouldn't be multithreaded lock (creationCounterMutex) { CreationIndex = creationCounter; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/EntitySpawner.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/EntitySpawner.cs index 625bc734c..d95b5bced 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/EntitySpawner.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/EntitySpawner.cs @@ -5,7 +5,6 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; -using System.Threading; namespace Barotrauma { @@ -206,7 +205,6 @@ namespace Barotrauma } private readonly Queue> spawnOrRemoveQueue; - private readonly object spawnOrRemoveQueueLock = new object(); public abstract class SpawnOrRemove : NetEntityEvent.IData { @@ -284,10 +282,7 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue1:ItemPrefabNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, onSpawned, condition, quality)); - } + spawnOrRemoveQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, onSpawned, condition, quality)); } public void AddItemToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null, int? quality = null, Action onSpawned = null) @@ -300,10 +295,7 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue2:ItemPrefabNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, onSpawned, condition, quality)); - } + spawnOrRemoveQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, onSpawned, condition, quality)); } public void AddItemToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null, int? quality = null, Action onSpawned = null, bool spawnIfInventoryFull = true, bool ignoreLimbSlots = false, InvSlotType slot = InvSlotType.None) @@ -316,15 +308,12 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, onSpawned, condition, quality) - { - SpawnIfInventoryFull = spawnIfInventoryFull, - IgnoreLimbSlots = ignoreLimbSlots, - Slot = slot - }); - } + spawnOrRemoveQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, onSpawned, condition, quality) + { + SpawnIfInventoryFull = spawnIfInventoryFull, + IgnoreLimbSlots = ignoreLimbSlots, + Slot = slot + }); } public void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 worldPosition, Action onSpawn = null) @@ -337,10 +326,7 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue4:SpeciesNameNullOrEmpty", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(new CharacterSpawnInfo(speciesName, worldPosition, onSpawn)); - } + spawnOrRemoveQueue.Enqueue(new CharacterSpawnInfo(speciesName, worldPosition, onSpawn)); } public void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 position, Submarine sub, Action onSpawn = null) @@ -353,10 +339,7 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue5:SpeciesNameNullOrEmpty", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(new CharacterSpawnInfo(speciesName, position, sub, onSpawn)); - } + spawnOrRemoveQueue.Enqueue(new CharacterSpawnInfo(speciesName, position, sub, onSpawn)); } public void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 worldPosition, CharacterInfo characterInfo, Action onSpawn = null) @@ -369,10 +352,7 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue4:SpeciesNameNullOrEmpty", GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(new CharacterSpawnInfo(speciesName, worldPosition, characterInfo, onSpawn)); - } + spawnOrRemoveQueue.Enqueue(new CharacterSpawnInfo(speciesName, worldPosition, characterInfo, onSpawn)); } public void AddEntityToRemoveQueue(Entity entity) @@ -395,10 +375,7 @@ namespace Barotrauma #endif } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(entity); - } + spawnOrRemoveQueue.Enqueue(entity); } public void AddItemToRemoveQueue(Item item) @@ -406,10 +383,7 @@ namespace Barotrauma if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (IsInRemoveQueue(item) || item.Removed) { return; } - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Enqueue(item); - } + spawnOrRemoveQueue.Enqueue(item); item.IsInRemoveQueue = true; foreach (var containedItem in item.ContainedItems) @@ -426,14 +400,11 @@ namespace Barotrauma /// public bool IsInSpawnQueue(Predicate predicate) { - lock (spawnOrRemoveQueueLock) + foreach (var spawnOrRemove in spawnOrRemoveQueue) { - foreach (var spawnOrRemove in spawnOrRemoveQueue) - { - if (spawnOrRemove.TryGet(out IEntitySpawnInfo spawnInfo) && predicate(spawnInfo)) { return true; } - } - return false; + if (spawnOrRemove.TryGet(out IEntitySpawnInfo spawnInfo) && predicate(spawnInfo)) { return true; } } + return false; } /// @@ -441,40 +412,29 @@ namespace Barotrauma /// public int CountSpawnQueue(Predicate predicate) { - lock (spawnOrRemoveQueueLock) + int count = 0; + foreach (var spawnOrRemove in spawnOrRemoveQueue) { - int count = 0; - foreach (var spawnOrRemove in spawnOrRemoveQueue) - { - if (spawnOrRemove.TryGet(out IEntitySpawnInfo spawnInfo) && predicate(spawnInfo)) { count++; } - } - return count; + if (spawnOrRemove.TryGet(out IEntitySpawnInfo spawnInfo) && predicate(spawnInfo)) { count++; } } + return count; } public bool IsInRemoveQueue(Entity entity) { - lock (spawnOrRemoveQueueLock) + foreach (var spawnOrRemove in spawnOrRemoveQueue) { - foreach (var spawnOrRemove in spawnOrRemoveQueue) - { - if (spawnOrRemove.TryGet(out Entity entityToRemove) && entityToRemove == entity) { return true; } - } - return false; + if (spawnOrRemove.TryGet(out Entity entityToRemove) && entityToRemove == entity) { return true; } } + return false; } public void Update(bool createNetworkEvents = true) { if (GameMain.NetworkMember is { IsClient: true }) { return; } - while (true) + while (spawnOrRemoveQueue.Count > 0) { - Either spawnOrRemove; - lock (spawnOrRemoveQueueLock) - { - if (spawnOrRemoveQueue.Count == 0) { break; } - spawnOrRemove = spawnOrRemoveQueue.Dequeue(); - } + if (!spawnOrRemoveQueue.TryDequeue(out var spawnOrRemove)) { break; } if (spawnOrRemove.TryGet(out Entity entityToRemove)) { if (entityToRemove is Item item) @@ -505,10 +465,7 @@ namespace Barotrauma public void Reset() { - lock (spawnOrRemoveQueueLock) - { - spawnOrRemoveQueue.Clear(); - } + spawnOrRemoveQueue.Clear(); #if CLIENT receivedEvents.Clear(); #endif diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 577324da2..e2fddef7c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -286,7 +286,6 @@ namespace Barotrauma } ); - // Process any physics operations queued during parallel updates PhysicsBodyQueue.ProcessPendingOperations(); #endif @@ -311,7 +310,6 @@ namespace Barotrauma MapEntity.UpdateAll((float)deltaTime, Camera.Instance, parallelOptions); - //StatusEffect.UpdateAll is not thread-safe and must be executed on the main thread StatusEffect.UpdateAll((float)deltaTime); #endif