From 9923c1b6e6e33fc982c3e61c457aa5210da3ae73 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 4 Feb 2024 17:08:39 +0300 Subject: [PATCH 1/3] Fix multiplayer/playlists lounge screen disposing rooms synchronously --- .../OnlinePlay/Lounge/Components/RoomsContainer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index ac6403bb34..8a3fbbf792 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -141,9 +141,18 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void removeRooms(IEnumerable rooms) { - foreach (var r in rooms) + foreach (var room in rooms) { - roomFlow.RemoveAll(d => d.Room == r, true); + var drawableRoom = roomFlow.SingleOrDefault(d => d.Room == room); + if (drawableRoom == null) + continue; + + // expire to trigger async disposal. the room still has to exist somewhere so we move it to internal content of RoomsContainer until next frame. + drawableRoom.Hide(); + drawableRoom.Expire(); + + roomFlow.Remove(drawableRoom, false); + AddInternal(drawableRoom); // selection may have a lease due to being in a sub screen. if (!SelectedRoom.Disabled) From 858f2fc7495867a600631e8683cefb193cc255fc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 18:39:04 +0300 Subject: [PATCH 2/3] Use `Clear` to trigger async disposal --- .../Lounge/Components/RoomsContainer.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 8a3fbbf792..fd9aa6cb0e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -126,7 +126,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components case NotifyCollectionChangedAction.Remove: Debug.Assert(args.OldItems != null); - removeRooms(args.OldItems.Cast()); + if (args.OldItems.Count == roomFlow.Count) + clearRooms(); + else + removeRooms(args.OldItems.Cast()); + break; } } @@ -141,18 +145,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void removeRooms(IEnumerable rooms) { - foreach (var room in rooms) + foreach (var r in rooms) { - var drawableRoom = roomFlow.SingleOrDefault(d => d.Room == room); - if (drawableRoom == null) - continue; - - // expire to trigger async disposal. the room still has to exist somewhere so we move it to internal content of RoomsContainer until next frame. - drawableRoom.Hide(); - drawableRoom.Expire(); - - roomFlow.Remove(drawableRoom, false); - AddInternal(drawableRoom); + roomFlow.RemoveAll(d => d.Room == r, true); // selection may have a lease due to being in a sub screen. if (!SelectedRoom.Disabled) @@ -160,6 +155,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + private void clearRooms() + { + roomFlow.Clear(); + + // selection may have a lease due to being in a sub screen. + if (!SelectedRoom.Disabled) + SelectedRoom.Value = null; + } + private void updateSorting() { foreach (var room in roomFlow) From 791423651640174323beef88c9607d5cde01690b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 18:49:59 +0300 Subject: [PATCH 3/3] Add explanatory note --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index fd9aa6cb0e..bff1a8c64c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -126,6 +126,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components case NotifyCollectionChangedAction.Remove: Debug.Assert(args.OldItems != null); + // clear operations have a separate path that benefits from async disposal, + // since disposing is quite expensive when performed on a high number of drawables synchronously. if (args.OldItems.Count == roomFlow.Count) clearRooms(); else