Skip to content

Commit 446489a

Browse files
committed
More cleanups of the managed side of terminal drivers.
1 parent 71da08b commit 446489a

10 files changed

+86
-169
lines changed

src/core/Terminal.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Vezel.Cathode.Terminals.Unix;
2-
using Vezel.Cathode.Terminals.Windows;
1+
using Vezel.Cathode.Terminals;
32

43
namespace Vezel.Cathode;
54

src/core/Terminals/NativeTerminalReader.cs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Vezel.Cathode.Terminals;
44

5-
internal abstract class NativeTerminalReader : TerminalReader
5+
internal sealed class NativeTerminalReader : TerminalReader
66
{
77
// Note that the buffer size used affects how many characters the Windows console host will allow the user to type
88
// in a single line (in cooked mode).
@@ -20,10 +20,20 @@ internal abstract class NativeTerminalReader : TerminalReader
2020

2121
public override sealed bool IsInteractive { get; }
2222

23-
protected NativeTerminalReader(NativeVirtualTerminal terminal, nuint handle)
23+
private readonly SemaphoreSlim _semaphore;
24+
25+
private readonly Action<nuint, CancellationToken>? _cancellationHook;
26+
27+
public NativeTerminalReader(
28+
NativeVirtualTerminal terminal,
29+
nuint handle,
30+
SemaphoreSlim semaphore,
31+
Action<nuint, CancellationToken>? cancellationHook)
2432
{
2533
Terminal = terminal;
2634
Handle = handle;
35+
_semaphore = semaphore;
36+
_cancellationHook = cancellationHook;
2737
Stream = new SynchronizedStream(new TerminalInputStream(this));
2838
TextReader =
2939
new SynchronizedTextReader(
@@ -32,15 +42,34 @@ protected NativeTerminalReader(NativeVirtualTerminal terminal, nuint handle)
3242
IsInteractive = TerminalInterop.IsInteractive(handle);
3343
}
3444

35-
protected abstract int ReadPartialNative(scoped Span<byte> buffer, CancellationToken cancellationToken);
45+
private unsafe int ReadPartialNative(scoped Span<byte> buffer, CancellationToken cancellationToken)
46+
{
47+
using var guard = Terminal.Control.Guard();
48+
49+
// If the descriptor is invalid, just present the illusion to the user that it has been redirected to /dev/null
50+
// or something along those lines, i.e. return EOF.
51+
if (buffer is [] || !IsValid)
52+
return 0;
53+
54+
using (_semaphore.Enter(cancellationToken))
55+
{
56+
_cancellationHook?.Invoke(Handle, cancellationToken);
57+
58+
int progress;
59+
60+
fixed (byte* p = buffer)
61+
TerminalInterop.Read(Handle, p, buffer.Length, &progress).ThrowIfError();
62+
63+
return progress;
64+
}
65+
}
3666

37-
protected override sealed int ReadPartialCore(scoped Span<byte> buffer)
67+
protected override int ReadPartialCore(scoped Span<byte> buffer)
3868
{
3969
return ReadPartialNative(buffer, default);
4070
}
4171

42-
protected override sealed ValueTask<int> ReadPartialCoreAsync(
43-
Memory<byte> buffer, CancellationToken cancellationToken)
72+
protected override ValueTask<int> ReadPartialCoreAsync(Memory<byte> buffer, CancellationToken cancellationToken)
4473
{
4574
// We currently have no native async support.
4675
return cancellationToken.IsCancellationRequested

src/core/Terminals/NativeTerminalWriter.cs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Vezel.Cathode.Terminals;
44

5-
internal abstract class NativeTerminalWriter : TerminalWriter
5+
internal sealed class NativeTerminalWriter : TerminalWriter
66
{
77
// Unlike NativeTerminalReader, the buffer size here is arbitrary and only has performance implications.
88
private const int WriteBufferSize = 256;
@@ -19,10 +19,20 @@ internal abstract class NativeTerminalWriter : TerminalWriter
1919

2020
public override sealed bool IsInteractive { get; }
2121

22-
protected NativeTerminalWriter(NativeVirtualTerminal terminal, nuint handle)
22+
private readonly SemaphoreSlim _semaphore;
23+
24+
private readonly Action<nuint, CancellationToken>? _cancellationHook;
25+
26+
public NativeTerminalWriter(
27+
NativeVirtualTerminal terminal,
28+
nuint handle,
29+
SemaphoreSlim semaphore,
30+
Action<nuint, CancellationToken>? cancellationHook)
2331
{
2432
Terminal = terminal;
2533
Handle = handle;
34+
_semaphore = semaphore;
35+
_cancellationHook = cancellationHook;
2636
Stream = new SynchronizedStream(new TerminalOutputStream(this));
2737
TextWriter =
2838
new SynchronizedTextWriter(new StreamWriter(Stream, Cathode.Terminal.Encoding, WriteBufferSize, true)
@@ -33,14 +43,34 @@ protected NativeTerminalWriter(NativeVirtualTerminal terminal, nuint handle)
3343
IsInteractive = TerminalInterop.IsInteractive(handle);
3444
}
3545

36-
protected abstract int WritePartialNative(scoped ReadOnlySpan<byte> buffer, CancellationToken cancellationToken);
46+
private unsafe int WritePartialNative(scoped ReadOnlySpan<byte> buffer, CancellationToken cancellationToken)
47+
{
48+
using var guard = Terminal.Control.Guard();
49+
50+
// If the descriptor is invalid, just present the illusion to the user that it has been redirected to /dev/null
51+
// or something along those lines, i.e. pretend we wrote everything.
52+
if (buffer is [] || !IsValid)
53+
return buffer.Length;
54+
55+
using (_semaphore.Enter(cancellationToken))
56+
{
57+
_cancellationHook?.Invoke(Handle, cancellationToken);
58+
59+
int progress;
60+
61+
fixed (byte* p = buffer)
62+
TerminalInterop.Write(Handle, p, buffer.Length, &progress).ThrowIfError();
63+
64+
return progress;
65+
}
66+
}
3767

38-
protected override sealed int WritePartialCore(scoped ReadOnlySpan<byte> buffer)
68+
protected override int WritePartialCore(scoped ReadOnlySpan<byte> buffer)
3969
{
4070
return WritePartialNative(buffer, default);
4171
}
4272

43-
protected override sealed ValueTask<int> WritePartialCoreAsync(
73+
protected override ValueTask<int> WritePartialCoreAsync(
4474
ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
4575
{
4676
// We currently have no native async support.

src/core/Terminals/Unix/UnixTerminalReader.cs

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/core/Terminals/Unix/UnixTerminalWriter.cs

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/core/Terminals/Unix/UnixCancellationPipe.cs renamed to src/core/Terminals/UnixCancellationPipe.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Vezel.Cathode.Native;
22

3-
namespace Vezel.Cathode.Terminals.Unix;
3+
namespace Vezel.Cathode.Terminals;
44

55
[SuppressMessage("", "CA1001")]
66
internal sealed class UnixCancellationPipe

src/core/Terminals/Unix/UnixVirtualTerminal.cs renamed to src/core/Terminals/UnixVirtualTerminal.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Vezel.Cathode.Terminals.Unix;
1+
namespace Vezel.Cathode.Terminals;
22

33
internal sealed class UnixVirtualTerminal : NativeVirtualTerminal
44
{
@@ -57,13 +57,17 @@ void HandleSignal(PosixSignalContext context)
5757
_sigChld = PosixSignalRegistration.Create(PosixSignal.SIGCHLD, HandleSignal);
5858
}
5959

60-
protected override UnixTerminalReader CreateReader(nuint handle, SemaphoreSlim semaphore)
60+
protected override NativeTerminalReader CreateReader(nuint handle, SemaphoreSlim semaphore)
6161
{
62-
return new(this, handle, semaphore);
62+
var pipe = new UnixCancellationPipe(write: false);
63+
64+
return new(this, handle, semaphore, cancellationHook: pipe.PollWithCancellation);
6365
}
6466

65-
protected override UnixTerminalWriter CreateWriter(nuint handle, SemaphoreSlim semaphore)
67+
protected override NativeTerminalWriter CreateWriter(nuint handle, SemaphoreSlim semaphore)
6668
{
67-
return new(this, handle, semaphore);
69+
var pipe = new UnixCancellationPipe(write: true);
70+
71+
return new(this, handle, semaphore, cancellationHook: pipe.PollWithCancellation);
6872
}
6973
}

src/core/Terminals/Windows/WindowsTerminalReader.cs

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/core/Terminals/Windows/WindowsTerminalWriter.cs

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/core/Terminals/Windows/WindowsVirtualTerminal.cs renamed to src/core/Terminals/WindowsVirtualTerminal.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Vezel.Cathode.Terminals.Windows;
1+
namespace Vezel.Cathode.Terminals;
22

33
internal sealed class WindowsVirtualTerminal : NativeVirtualTerminal
44
{
@@ -20,13 +20,13 @@ private WindowsVirtualTerminal()
2020
{
2121
}
2222

23-
protected override WindowsTerminalReader CreateReader(nuint handle, SemaphoreSlim semaphore)
23+
protected override NativeTerminalReader CreateReader(nuint handle, SemaphoreSlim semaphore)
2424
{
25-
return new(this, handle, semaphore);
25+
return new(this, handle, semaphore, cancellationHook: null);
2626
}
2727

28-
protected override WindowsTerminalWriter CreateWriter(nuint handle, SemaphoreSlim semaphore)
28+
protected override NativeTerminalWriter CreateWriter(nuint handle, SemaphoreSlim semaphore)
2929
{
30-
return new(this, handle, semaphore);
30+
return new(this, handle, semaphore, cancellationHook: null);
3131
}
3232
}

0 commit comments

Comments
 (0)