remove locking from other connections too
This commit is contained in:
		
							parent
							
								
									b421b2b491
								
							
						
					
					
						commit
						efeb4345b3
					
				
					 4 changed files with 30 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -27,8 +27,6 @@ internal sealed class ClientScreenServerConnection(
 | 
			
		|||
        ? null
 | 
			
		||||
        : new PlayerScreenData(logger, player);
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask HandleMessageLockedAsync(Memory<byte> buffer) => throw new UnreachableException();
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask HandleMessageAsync(Memory<byte> _)
 | 
			
		||||
    {
 | 
			
		||||
        if (_wantsFrameOnTick != 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ internal sealed class ControlsServerConnection(
 | 
			
		|||
        Shoot = 0x05
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask HandleMessageLockedAsync(Memory<byte> buffer)
 | 
			
		||||
    protected override ValueTask HandleMessageAsync(Memory<byte> buffer)
 | 
			
		||||
    {
 | 
			
		||||
        var type = (MessageType)buffer.Span[0];
 | 
			
		||||
        var control = (InputType)buffer.Span[1];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,37 +11,37 @@ internal sealed class PlayerInfoConnection(
 | 
			
		|||
    MapEntityManager entityManager
 | 
			
		||||
) : WebsocketServerConnection(logger, new ByteChannelWebSocket(rawSocket, logger, 0))
 | 
			
		||||
{
 | 
			
		||||
    private bool _wantsInfoOnTick = true;
 | 
			
		||||
    private byte[] _lastMessage = [];
 | 
			
		||||
    private int _wantsInfoOnTick = 1;
 | 
			
		||||
    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();
 | 
			
		||||
        if (response == null)
 | 
			
		||||
        {
 | 
			
		||||
            Logger.LogTrace("cannot respond directly, increasing wanted frames");
 | 
			
		||||
            _wantsInfoOnTick = true;
 | 
			
		||||
            return ValueTask.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
        var next = Interlocked.Exchange(ref _nextMessage, null);
 | 
			
		||||
        if (next != null)
 | 
			
		||||
            return SendAndDisposeAsync(next);
 | 
			
		||||
 | 
			
		||||
        Logger.LogTrace("responding directly");
 | 
			
		||||
        return Socket.SendTextAsync(response);
 | 
			
		||||
        _wantsInfoOnTick = 1;
 | 
			
		||||
        return ValueTask.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ValueTask OnGameTickAsync() => LockedAsync(() =>
 | 
			
		||||
    public async ValueTask OnGameTickAsync()
 | 
			
		||||
    {
 | 
			
		||||
        if (!_wantsInfoOnTick)
 | 
			
		||||
            return ValueTask.CompletedTask;
 | 
			
		||||
        await Task.Yield();
 | 
			
		||||
 | 
			
		||||
        var response = GetMessageToSend();
 | 
			
		||||
        if (response == null)
 | 
			
		||||
            return ValueTask.CompletedTask;
 | 
			
		||||
        var wantsNow = Interlocked.Exchange(ref _wantsInfoOnTick, 0) != 0;
 | 
			
		||||
 | 
			
		||||
        Logger.LogTrace("responding indirectly");
 | 
			
		||||
        return Socket.SendTextAsync(response);
 | 
			
		||||
    });
 | 
			
		||||
        if (wantsNow)
 | 
			
		||||
        {
 | 
			
		||||
            await SendAndDisposeAsync(response);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private byte[]? GetMessageToSend()
 | 
			
		||||
        Interlocked.Exchange(ref _nextMessage, response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private byte[] GetMessageToSend()
 | 
			
		||||
    {
 | 
			
		||||
        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 response = JsonSerializer.SerializeToUtf8Bytes(info, AppSerializerContext.Default.PlayerInfo);
 | 
			
		||||
 | 
			
		||||
        if (response.SequenceEqual(_lastMessage))
 | 
			
		||||
            return null;
 | 
			
		||||
        // TODO: switch to async version with pre-allocated buffer / IMemoryOwner
 | 
			
		||||
        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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,10 +22,7 @@ internal abstract class WebsocketServerConnection(
 | 
			
		|||
        Logger.LogTrace("done receiving");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected virtual ValueTask HandleMessageAsync(Memory<byte> buffer)
 | 
			
		||||
        => LockedAsync(() => HandleMessageLockedAsync(buffer));
 | 
			
		||||
 | 
			
		||||
    protected abstract ValueTask HandleMessageLockedAsync(Memory<byte> buffer);
 | 
			
		||||
    protected abstract ValueTask HandleMessageAsync(Memory<byte> buffer);
 | 
			
		||||
 | 
			
		||||
    protected async ValueTask LockedAsync(Func<ValueTask> action)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue