#nullable enable
using System.Collections.Concurrent;
namespace Terminal.Gui;
///
/// Base class for reading console input in perpetual loop
///
///
public abstract class ConsoleInput : IConsoleInput
{
private ConcurrentQueue? _inputBuffer;
///
/// Determines how to get the current system type, adjust
/// in unit tests to simulate specific timings.
///
public Func Now { get; set; } = () => DateTime.Now;
///
public virtual void Dispose () { }
///
public void Initialize (ConcurrentQueue inputBuffer) { _inputBuffer = inputBuffer; }
///
public void Run (CancellationToken token)
{
try
{
if (_inputBuffer == null)
{
throw new ("Cannot run input before Initialization");
}
do
{
DateTime dt = Now ();
while (Peek ())
{
foreach (T r in Read ())
{
_inputBuffer.Enqueue (r);
}
}
TimeSpan took = Now () - dt;
TimeSpan sleepFor = TimeSpan.FromMilliseconds (20) - took;
Logging.DrainInputStream.Record (took.Milliseconds);
if (sleepFor.Milliseconds > 0)
{
Task.Delay (sleepFor, token).Wait (token);
}
token.ThrowIfCancellationRequested ();
}
while (!token.IsCancellationRequested);
}
catch (OperationCanceledException)
{ }
}
///
/// When implemented in a derived class, returns true if there is data available
/// to read from console.
///
///
protected abstract bool Peek ();
///
/// Returns the available data without blocking, called when
/// returns .
///
///
protected abstract IEnumerable Read ();
}