1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 08:22:56 +08:00

Remove locking from SpectatorClient

This commit is contained in:
smoogipoo 2021-05-20 18:37:27 +09:00
parent 6eff8d513e
commit 10597f7e6a

View File

@ -38,8 +38,6 @@ namespace osu.Game.Online.Spectator
private readonly List<int> watchingUsers = new List<int>();
private readonly object userLock = new object();
public IBindableList<int> PlayingUsers => playingUsers;
private readonly BindableList<int> playingUsers = new BindableList<int>();
@ -81,18 +79,13 @@ namespace osu.Game.Online.Spectator
[BackgroundDependencyLoader]
private void load()
{
IsConnected.BindValueChanged(connected =>
IsConnected.BindValueChanged(connected => Schedule(() =>
{
if (connected.NewValue)
{
// get all the users that were previously being watched
int[] users;
lock (userLock)
{
users = watchingUsers.ToArray();
watchingUsers.Clear();
}
int[] users = watchingUsers.ToArray();
watchingUsers.Clear();
// resubscribe to watched users.
foreach (var userId in users)
@ -104,18 +97,15 @@ namespace osu.Game.Online.Spectator
}
else
{
lock (userLock)
{
playingUsers.Clear();
playingUserStates.Clear();
}
playingUsers.Clear();
playingUserStates.Clear();
}
}, true);
}), true);
}
Task ISpectatorClient.UserBeganPlaying(int userId, SpectatorState state)
{
lock (userLock)
Schedule(() =>
{
if (!playingUsers.Contains(userId))
playingUsers.Add(userId);
@ -125,29 +115,29 @@ namespace osu.Game.Online.Spectator
// We don't want the user states to update unless the player is being watched, otherwise calling BindUserBeganPlaying() can lead to double invocations.
if (watchingUsers.Contains(userId))
playingUserStates[userId] = state;
}
OnUserBeganPlaying?.Invoke(userId, state);
OnUserBeganPlaying?.Invoke(userId, state);
});
return Task.CompletedTask;
}
Task ISpectatorClient.UserFinishedPlaying(int userId, SpectatorState state)
{
lock (userLock)
Schedule(() =>
{
playingUsers.Remove(userId);
playingUserStates.Remove(userId);
}
OnUserFinishedPlaying?.Invoke(userId, state);
OnUserFinishedPlaying?.Invoke(userId, state);
});
return Task.CompletedTask;
}
Task ISpectatorClient.UserSentFrames(int userId, FrameDataBundle data)
{
OnNewFrames?.Invoke(userId, data);
Schedule(() => OnNewFrames?.Invoke(userId, data));
return Task.CompletedTask;
}
@ -182,23 +172,17 @@ namespace osu.Game.Online.Spectator
public void WatchUser(int userId)
{
lock (userLock)
{
if (watchingUsers.Contains(userId))
return;
if (watchingUsers.Contains(userId))
return;
watchingUsers.Add(userId);
}
watchingUsers.Add(userId);
WatchUserInternal(userId);
}
public void StopWatchingUser(int userId)
{
lock (userLock)
{
watchingUsers.Remove(userId);
}
watchingUsers.Remove(userId);
StopWatchingUserInternal(userId);
}
@ -262,8 +246,7 @@ namespace osu.Game.Online.Spectator
/// <returns><c>true</c> if successful (the user is playing), <c>false</c> otherwise.</returns>
public bool TryGetPlayingUserState(int userId, out SpectatorState state)
{
lock (userLock)
return playingUserStates.TryGetValue(userId, out state);
return playingUserStates.TryGetValue(userId, out state);
}
/// <summary>
@ -274,16 +257,13 @@ namespace osu.Game.Online.Spectator
public void BindUserBeganPlaying(Action<int, SpectatorState> callback, bool runOnceImmediately = false)
{
// The lock is taken before the event is subscribed to to prevent doubling of events.
lock (userLock)
{
OnUserBeganPlaying += callback;
OnUserBeganPlaying += callback;
if (!runOnceImmediately)
return;
if (!runOnceImmediately)
return;
foreach (var (userId, state) in playingUserStates)
callback(userId, state);
}
foreach (var (userId, state) in playingUserStates)
callback(userId, state);
}
}
}