remove locking from other connections too

This commit is contained in:
Vinzenz Schroeter 2024-05-02 19:07:04 +02:00 committed by RobbersDaughter
parent 0e93b1356f
commit d9e9c28976
4 changed files with 30 additions and 32 deletions

View file

@ -27,8 +27,6 @@ internal sealed class ClientScreenServerConnection(
? null ? null
: new PlayerScreenData(logger, player); : new PlayerScreenData(logger, player);
protected override ValueTask HandleMessageLockedAsync(Memory<byte> buffer) => throw new UnreachableException();
protected override ValueTask HandleMessageAsync(Memory<byte> _) protected override ValueTask HandleMessageAsync(Memory<byte> _)
{ {
if (_wantsFrameOnTick != 0) if (_wantsFrameOnTick != 0)

View file

@ -23,7 +23,7 @@ internal sealed class ControlsServerConnection(
Shoot = 0x05 Shoot = 0x05
} }
protected override ValueTask HandleMessageLockedAsync(Memory<byte> buffer) protected override ValueTask HandleMessageAsync(Memory<byte> buffer)
{ {
var type = (MessageType)buffer.Span[0]; var type = (MessageType)buffer.Span[0];
var control = (InputType)buffer.Span[1]; var control = (InputType)buffer.Span[1];

View file

@ -11,37 +11,37 @@ internal sealed class PlayerInfoConnection(
MapEntityManager entityManager MapEntityManager entityManager
) : WebsocketServerConnection(logger, new ByteChannelWebSocket(rawSocket, logger, 0)) ) : WebsocketServerConnection(logger, new ByteChannelWebSocket(rawSocket, logger, 0))
{ {
private bool _wantsInfoOnTick = true; private int _wantsInfoOnTick = 1;
private byte[] _lastMessage = []; private byte[]? _lastMessage = null;
private byte[]? _nextMessage = null;
protected override ValueTask HandleMessageLockedAsync(Memory<byte> buffer) protected override ValueTask HandleMessageAsync(Memory<byte> buffer)
{ {
var response = GetMessageToSend(); var next = Interlocked.Exchange(ref _nextMessage, null);
if (response == null) if (next != null)
{ return SendAndDisposeAsync(next);
Logger.LogTrace("cannot respond directly, increasing wanted frames");
_wantsInfoOnTick = true;
return ValueTask.CompletedTask;
}
Logger.LogTrace("responding directly"); _wantsInfoOnTick = 1;
return Socket.SendTextAsync(response); return ValueTask.CompletedTask;
} }
public ValueTask OnGameTickAsync() => LockedAsync(() => public async ValueTask OnGameTickAsync()
{ {
if (!_wantsInfoOnTick) await Task.Yield();
return ValueTask.CompletedTask;
var response = GetMessageToSend(); var response = GetMessageToSend();
if (response == null) var wantsNow = Interlocked.Exchange(ref _wantsInfoOnTick, 0) != 0;
return ValueTask.CompletedTask;
Logger.LogTrace("responding indirectly"); if (wantsNow)
return Socket.SendTextAsync(response); {
}); await SendAndDisposeAsync(response);
return;
}
private byte[]? GetMessageToSend() Interlocked.Exchange(ref _nextMessage, response);
}
private byte[] GetMessageToSend()
{ {
var tank = entityManager.GetCurrentTankOfPlayer(player); var tank = entityManager.GetCurrentTankOfPlayer(player);
@ -53,11 +53,14 @@ internal sealed class PlayerInfoConnection(
} }
var info = new PlayerInfo(player.Name, player.Scores, player.Controls.ToDisplayString(), tankInfo); var info = new PlayerInfo(player.Name, player.Scores, player.Controls.ToDisplayString(), tankInfo);
var response = JsonSerializer.SerializeToUtf8Bytes(info, AppSerializerContext.Default.PlayerInfo);
if (response.SequenceEqual(_lastMessage)) // TODO: switch to async version with pre-allocated buffer / IMemoryOwner
return null; return JsonSerializer.SerializeToUtf8Bytes(info, AppSerializerContext.Default.PlayerInfo);
}
return _lastMessage = response; private async ValueTask SendAndDisposeAsync(byte[] data)
{
await Socket.SendTextAsync(data);
Interlocked.Exchange(ref _lastMessage, data);
} }
} }

View file

@ -22,10 +22,7 @@ internal abstract class WebsocketServerConnection(
Logger.LogTrace("done receiving"); Logger.LogTrace("done receiving");
} }
protected virtual ValueTask HandleMessageAsync(Memory<byte> buffer) protected abstract ValueTask HandleMessageAsync(Memory<byte> buffer);
=> LockedAsync(() => HandleMessageLockedAsync(buffer));
protected abstract ValueTask HandleMessageLockedAsync(Memory<byte> buffer);
protected async ValueTask LockedAsync(Func<ValueTask> action) protected async ValueTask LockedAsync(Func<ValueTask> action)
{ {