Phase 9: FeedbackPipeServer (\\.\pipe\riojoy-feedback) + loopback UDP share a forgiving text line protocol into FeedbackRouter; CoalescingLampScheduler rate- governs the 9600-baud link; plasma finally wired into activation (greeting, teardown blank, PlasmaDisplay write lock); ViGEm FeedbackReceived drives RumbleLampAdapter. Per-profile Feedback config, docs/FEEDBACK.md, 425 tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
51 lines
1.7 KiB
C#
51 lines
1.7 KiB
C#
using System.Threading.Channels;
|
|
using RioJoy.Core.Serial;
|
|
|
|
namespace RioJoy.Core.Tests.Serial;
|
|
|
|
/// <summary>
|
|
/// <see cref="IRioTransport"/> whose first write blocks until <see cref="Open"/>
|
|
/// — lets a test park one writer mid-sequence while another tries to cut in
|
|
/// (write-lock and latest-wins assertions).
|
|
/// </summary>
|
|
internal sealed class GatedTransport : IRioTransport
|
|
{
|
|
private readonly Channel<byte[]> _writes = Channel.CreateUnbounded<byte[]>();
|
|
private readonly SemaphoreSlim _gate = new(0, 1);
|
|
private readonly object _armLock = new();
|
|
private bool _gateArmed = true;
|
|
|
|
public string Description => "gated";
|
|
|
|
/// <summary>Release the parked first write.</summary>
|
|
public void Open() => _gate.Release();
|
|
|
|
public Task<int> ReadAsync(byte[] buffer, CancellationToken cancellationToken) =>
|
|
Task.FromResult(0);
|
|
|
|
public async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
|
|
{
|
|
bool wait;
|
|
lock (_armLock)
|
|
{
|
|
wait = _gateArmed;
|
|
_gateArmed = false;
|
|
}
|
|
if (wait)
|
|
await _gate.WaitAsync(cancellationToken);
|
|
_writes.Writer.TryWrite((byte[])data.Clone());
|
|
}
|
|
|
|
/// <summary>Read the next write, failing if none arrives in time.</summary>
|
|
public async Task<byte[]> NextWriteAsync(TimeSpan? timeout = null)
|
|
{
|
|
using var cts = new CancellationTokenSource(timeout ?? TimeSpan.FromSeconds(5));
|
|
return await _writes.Reader.ReadAsync(cts.Token);
|
|
}
|
|
|
|
/// <summary>True when no further write has arrived.</summary>
|
|
public bool NoMoreWrites => !_writes.Reader.TryPeek(out _);
|
|
|
|
public void Dispose() { }
|
|
}
|