Core/Instances: Sprinkle some thread safety on InstanceLockMgr

Port From (https://github.com/TrinityCore/TrinityCore/commit/0be72f68c33617d78a4139f3e667b03d0a22a435)
This commit is contained in:
hondacrx
2022-10-04 16:57:02 -04:00
parent 2b09e4227b
commit 8d2770081b
@@ -36,6 +36,7 @@ namespace Game.Maps
public class InstanceLockManager : Singleton<InstanceLockManager> public class InstanceLockManager : Singleton<InstanceLockManager>
{ {
object _lockObject = new();
Dictionary<ObjectGuid, Dictionary<InstanceLockKey, InstanceLock>> _temporaryInstanceLocksByPlayer = new(); // locks stored here before any boss gets killed Dictionary<ObjectGuid, Dictionary<InstanceLockKey, InstanceLock>> _temporaryInstanceLocksByPlayer = new(); // locks stored here before any boss gets killed
Dictionary<ObjectGuid, Dictionary<InstanceLockKey, InstanceLock>> _instanceLocksByPlayer = new(); Dictionary<ObjectGuid, Dictionary<InstanceLockKey, InstanceLock>> _instanceLocksByPlayer = new();
Dictionary<uint, SharedInstanceLockData> _instanceLockDataById = new(); Dictionary<uint, SharedInstanceLockData> _instanceLockDataById = new();
@@ -150,7 +151,8 @@ namespace Game.Maps
public InstanceLock FindActiveInstanceLock(ObjectGuid playerGuid, MapDb2Entries entries) public InstanceLock FindActiveInstanceLock(ObjectGuid playerGuid, MapDb2Entries entries)
{ {
return FindActiveInstanceLock(playerGuid, entries, false, true); lock(_lockObject)
return FindActiveInstanceLock(playerGuid, entries, false, true);
} }
public InstanceLock FindActiveInstanceLock(ObjectGuid playerGuid, MapDb2Entries entries, bool ignoreTemporary, bool ignoreExpired) public InstanceLock FindActiveInstanceLock(ObjectGuid playerGuid, MapDb2Entries entries, bool ignoreTemporary, bool ignoreExpired)
@@ -200,24 +202,27 @@ namespace Game.Maps
InstanceLock instanceLock = FindActiveInstanceLock(playerGuid, entries, true, true); InstanceLock instanceLock = FindActiveInstanceLock(playerGuid, entries, true, true);
if (instanceLock == null) if (instanceLock == null)
{ {
// Move lock from temporary storage if it exists there lock (_lockObject)
// This is to avoid destroying expired locks before any boss is killed in a fresh lock
// player can still change his mind, exit instance and reactivate old lock
var playerLocks = _temporaryInstanceLocksByPlayer.LookupByKey(playerGuid);
if (playerLocks != null)
{ {
var playerInstanceLock = playerLocks.LookupByKey(entries.GetKey()); // Move lock from temporary storage if it exists there
if (playerInstanceLock != null) // This is to avoid destroying expired locks before any boss is killed in a fresh lock
// player can still change his mind, exit instance and reactivate old lock
var playerLocks = _temporaryInstanceLocksByPlayer.LookupByKey(playerGuid);
if (playerLocks != null)
{ {
instanceLock = playerInstanceLock; var playerInstanceLock = playerLocks.LookupByKey(entries.GetKey());
_instanceLocksByPlayer[playerGuid][entries.GetKey()] = instanceLock; if (playerInstanceLock != null)
{
instanceLock = playerInstanceLock;
_instanceLocksByPlayer[playerGuid][entries.GetKey()] = instanceLock;
playerLocks.Remove(entries.GetKey()); playerLocks.Remove(entries.GetKey());
if (playerLocks.Empty()) if (playerLocks.Empty())
_temporaryInstanceLocksByPlayer.Remove(playerGuid); _temporaryInstanceLocksByPlayer.Remove(playerGuid);
Log.outDebug(LogFilter.Instance, $"[{entries.Map.Id}-{entries.Map.MapName[Global.WorldMgr.GetDefaultDbcLocale()]} | " + Log.outDebug(LogFilter.Instance, $"[{entries.Map.Id}-{entries.Map.MapName[Global.WorldMgr.GetDefaultDbcLocale()]} | " +
$"{entries.MapDifficulty.DifficultyID}-{CliDB.DifficultyStorage.LookupByKey(entries.MapDifficulty.DifficultyID).Name}] Promoting temporary lock to permanent for {playerGuid} in instance {updateEvent.InstanceId}"); $"{entries.MapDifficulty.DifficultyID}-{CliDB.DifficultyStorage.LookupByKey(entries.MapDifficulty.DifficultyID).Name}] Promoting temporary lock to permanent for {playerGuid} in instance {updateEvent.InstanceId}");
}
} }
} }
} }
@@ -237,7 +242,9 @@ namespace Game.Maps
instanceLock = new InstanceLock(entries.MapDifficulty.MapID, (Difficulty)entries.MapDifficulty.DifficultyID, instanceLock = new InstanceLock(entries.MapDifficulty.MapID, (Difficulty)entries.MapDifficulty.DifficultyID,
GetNextResetTime(entries), updateEvent.InstanceId); GetNextResetTime(entries), updateEvent.InstanceId);
_instanceLocksByPlayer[playerGuid][entries.GetKey()] = instanceLock; lock(_lockObject)
_instanceLocksByPlayer[playerGuid][entries.GetKey()] = instanceLock;
Log.outDebug(LogFilter.Instance, $"[{entries.Map.Id}-{entries.Map.MapName[Global.WorldMgr.GetDefaultDbcLocale()]} | " + Log.outDebug(LogFilter.Instance, $"[{entries.Map.Id}-{entries.Map.MapName[Global.WorldMgr.GetDefaultDbcLocale()]} | " +
$"{entries.MapDifficulty.DifficultyID}-{CliDB.DifficultyStorage.LookupByKey(entries.MapDifficulty.DifficultyID).Name}] Created new instance lock for {playerGuid} in instance {updateEvent.InstanceId}"); $"{entries.MapDifficulty.DifficultyID}-{CliDB.DifficultyStorage.LookupByKey(entries.MapDifficulty.DifficultyID).Name}] Created new instance lock for {playerGuid} in instance {updateEvent.InstanceId}");
} }