From d3b2e2b36eebcb6913244df225f4007bd014708b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Dec 2020 14:43:17 +0900 Subject: [PATCH] Change locking method to better allow cross-thread locking --- .../RealtimeMultiplayer/LockUntilDisposal.cs | 24 ------------------- .../RealtimeMultiplayer/MultiplayerRoom.cs | 20 +++++++++++++++- 2 files changed, 19 insertions(+), 25 deletions(-) delete mode 100644 osu.Game/Online/RealtimeMultiplayer/LockUntilDisposal.cs diff --git a/osu.Game/Online/RealtimeMultiplayer/LockUntilDisposal.cs b/osu.Game/Online/RealtimeMultiplayer/LockUntilDisposal.cs deleted file mode 100644 index cd16fce2ee..0000000000 --- a/osu.Game/Online/RealtimeMultiplayer/LockUntilDisposal.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Threading; - -namespace osu.Game.Online.RealtimeMultiplayer -{ - public readonly struct LockUntilDisposal : IDisposable - { - private readonly object lockTarget; - - public LockUntilDisposal(object lockTarget) - { - this.lockTarget = lockTarget; - Monitor.Enter(lockTarget); - } - - public void Dispose() - { - Monitor.Exit(lockTarget); - } - } -} diff --git a/osu.Game/Online/RealtimeMultiplayer/MultiplayerRoom.cs b/osu.Game/Online/RealtimeMultiplayer/MultiplayerRoom.cs index 5704ddd675..e009a34707 100644 --- a/osu.Game/Online/RealtimeMultiplayer/MultiplayerRoom.cs +++ b/osu.Game/Online/RealtimeMultiplayer/MultiplayerRoom.cs @@ -5,7 +5,9 @@ using System; using System.Collections.Generic; +using System.Threading; using Newtonsoft.Json; +using osu.Framework.Allocation; namespace osu.Game.Online.RealtimeMultiplayer { @@ -48,10 +50,26 @@ namespace osu.Game.Online.RealtimeMultiplayer RoomID = roomId; } + private object updateLock = new object(); + + private ManualResetEventSlim freeForWrite = new ManualResetEventSlim(true); + /// /// Request a lock on this room to perform a thread-safe update. /// - public LockUntilDisposal LockForUpdate() => new LockUntilDisposal(writeLock); + public IDisposable LockForUpdate() + { + // ReSharper disable once InconsistentlySynchronizedField + freeForWrite.Wait(); + + lock (updateLock) + { + freeForWrite.Wait(); + freeForWrite.Reset(); + + return new ValueInvokeOnDisposal(this, r => freeForWrite.Set()); + } + } public override string ToString() => $"RoomID:{RoomID} Host:{Host?.UserID} Users:{Users.Count} State:{State} Settings: [{Settings}]"; }