WIP Make static collections thread-safe using ThreadStatic and ThreadLocal
Refactored various static and instance collections to use [ThreadStatic], ThreadLocal, or local variables to prevent concurrent modification issues during parallel updates. This affects status effect targets, affliction lists, damage modifiers, and cached data in Character, CharacterHealth, Limb, Explosion, Hull, Submarine, and ToolBox classes. Also replaced Dictionary caches with ConcurrentDictionary where appropriate for thread safety.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
@@ -75,7 +76,7 @@ namespace Barotrauma
|
||||
return !corrected;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> cachedFileNames = new Dictionary<string, string>();
|
||||
private static readonly ConcurrentDictionary<string, string> cachedFileNames = new ConcurrentDictionary<string, string>();
|
||||
|
||||
public static string CorrectFilenameCase(string filename, out bool corrected, string directory = "")
|
||||
{
|
||||
@@ -153,7 +154,7 @@ namespace Barotrauma
|
||||
if (i < subDirs.Length - 1) { filename += "/"; }
|
||||
}
|
||||
|
||||
cachedFileNames.Add(originalFilename, filename);
|
||||
cachedFileNames.TryAdd(originalFilename, filename);
|
||||
return filename;
|
||||
}
|
||||
|
||||
@@ -355,32 +356,26 @@ namespace Barotrauma
|
||||
return text;
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<string>> cachedLines = new Dictionary<string, List<string>>();
|
||||
private static readonly ConcurrentDictionary<string, List<string>> cachedLines = new ConcurrentDictionary<string, List<string>>();
|
||||
public static string GetRandomLine(string filePath, Rand.RandSync randSync = Rand.RandSync.ServerAndClient)
|
||||
{
|
||||
List<string> lines;
|
||||
if (cachedLines.ContainsKey(filePath))
|
||||
{
|
||||
lines = cachedLines[filePath];
|
||||
}
|
||||
else
|
||||
List<string> lines = cachedLines.GetOrAdd(filePath, path =>
|
||||
{
|
||||
try
|
||||
{
|
||||
lines = File.ReadAllLines(filePath, catchUnauthorizedAccessExceptions: false).ToList();
|
||||
cachedLines.Add(filePath, lines);
|
||||
if (lines.Count == 0)
|
||||
var fileLines = File.ReadAllLines(path, catchUnauthorizedAccessExceptions: false).ToList();
|
||||
if (fileLines.Count == 0)
|
||||
{
|
||||
DebugConsole.ThrowError("File \"" + filePath + "\" is empty!");
|
||||
return "";
|
||||
DebugConsole.ThrowError("File \"" + path + "\" is empty!");
|
||||
}
|
||||
return fileLines;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't open file \"" + filePath + "\"!", e);
|
||||
return "";
|
||||
DebugConsole.ThrowError("Couldn't open file \"" + path + "\"!", e);
|
||||
return new List<string>();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (lines.Count == 0) return "";
|
||||
return lines[Rand.Range(0, lines.Count, randSync)];
|
||||
|
||||
Reference in New Issue
Block a user