From a4039451f30ef2c1bb90b7ca47b42ba4a3076de6 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Wed, 3 Apr 2024 15:53:24 +0000 Subject: [PATCH] use ReaderWriterLockSlim for lock Room.clients --- src/Core/GauntletRoom.cs | 5 ++++- src/Core/Room.cs | 32 +++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/Core/GauntletRoom.cs b/src/Core/GauntletRoom.cs index 1f6fb4d..6a5a386 100644 --- a/src/Core/GauntletRoom.cs +++ b/src/Core/GauntletRoom.cs @@ -85,7 +85,8 @@ public class GauntletRoom : Room { } public bool ProcessResult(Client client, string resultA, string resultB) { - lock (base.roomLock) { + base.roomLock.EnterWriteLock(); + try { players[client].resultA = resultA; players[client].resultB = resultB; @@ -112,6 +113,8 @@ public class GauntletRoom : Room { Send(packet); return true; + } finally { + base.roomLock.ExitWriteLock(); } } diff --git a/src/Core/Room.cs b/src/Core/Room.cs index e832370..fb493b9 100644 --- a/src/Core/Room.cs +++ b/src/Core/Room.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using sodoffmmo.Data; namespace sodoffmmo.Core; @@ -8,7 +9,7 @@ public class Room { protected static Dictionary rooms = new(); List clients = new(); - protected object roomLock = new object(); + protected ReaderWriterLockSlim roomLock = new ReaderWriterLockSlim(); public int Id { get; private set; } public string Name { get; private set; } @@ -38,39 +39,52 @@ public class Room { public IEnumerable Clients { get { List list; - lock (roomLock) { - list = new List(clients); + roomLock.EnterReadLock(); + try { + return new List(clients); + } finally { + roomLock.ExitReadLock(); } - return list; } } public void AddClient(Client client) { - lock (roomLock) { + roomLock.EnterWriteLock(); + try { if (IsRemoved) throw new Exception("Call AddClient on removed room"); client.Send(RespondJoinRoom()); // NOTE: send RespondJoinRoom() and add client to clients as atomic operation // to make sure to client get full list of players in room clients.Add(client); + } finally { + roomLock.ExitWriteLock(); } } public void RemoveClient(Client client) { - lock (roomLock) { + roomLock.EnterWriteLock(); + try { clients.Remove(client); if (AutoRemove && ClientsCount == 0) { IsRemoved = true; rooms.Remove(Name); } + } finally { + roomLock.ExitWriteLock(); } } public void Send(NetworkPacket packet, Client? skip = null) { - foreach (var roomClient in clients) { - if (roomClient != skip) { - roomClient.Send(packet); + roomLock.EnterReadLock(); + try { + foreach (var roomClient in clients) { + if (roomClient != skip) { + roomClient.Send(packet); + } } + } finally { + roomLock.ExitReadLock(); } }