IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
AsyncDiagnosticChannelWriter.cs
Go to the documentation of this file.
1using System;
2using System.Buffers;
3using System.Threading;
4using System.Threading.Channels;
5using System.Threading.Tasks;
6
8{
9
14 {
15
16 static readonly UnboundedChannelOptions unboundedChannelOptions = new UnboundedChannelOptions()
17 {
18 SingleWriter = false,
19 SingleReader = true,
20 AllowSynchronousContinuations = true
21 };
22
23 readonly IBufferWriter<byte> _writer;
24 readonly Channel<(IMemoryOwner<byte> Owner, int Length)> _channel = Channel.CreateUnbounded<(IMemoryOwner<byte> Owner, int Length)>(unboundedChannelOptions);
25
26 Task? _task;
27 CancellationTokenSource? _stop;
28
34 public AsyncDiagnosticChannelWriter(IBufferWriter<byte> writer)
35 {
36 _writer = writer ?? throw new ArgumentNullException(nameof(writer));
37 }
38
43 public void Write(IMemoryOwner<byte> owner, int length)
44 {
45 if (owner is null)
46 throw new ArgumentNullException(nameof(owner));
47
48 if (_stop == null || _task == null)
49 {
50 lock (this)
51 {
52 if (_stop == null || _task == null)
53 {
54 _stop = new CancellationTokenSource();
55 _task = DequeueLoop(_stop.Token);
56 }
57 }
58 }
59
60 _channel.Writer.TryWrite((owner, length));
61 }
62
66 async Task DequeueLoop(CancellationToken cancellationToken)
67 {
68 while (cancellationToken.IsCancellationRequested == false)
69 {
70 try
71 {
72 while (await _channel.Reader.WaitToReadAsync(cancellationToken))
73 while (_channel.Reader.TryRead(out var item))
74 WriteData(item.Owner, item.Length);
75 }
76 catch (OperationCanceledException)
77 {
78 // ignore
79 }
80 }
81 }
82
88 void WriteData(IMemoryOwner<byte> owner, int length)
89 {
90 // allocate memory and copy data
91 var buffer = _writer.GetMemory(length);
92 owner.Memory.Slice(0, length).CopyTo(buffer);
93 _writer.Advance(length);
94
95 // we are finished with the owner
96 owner.Dispose();
97 }
98
102 public void Dispose()
103 {
104 lock (this)
105 {
106 // stop dequeue task
107 _stop?.Cancel();
108 _task?.GetAwaiter().GetResult();
109 _stop = null;
110 _task = null;
111
112 // empty the channel to pick up any straggling items not caught by the dequeue thread
113 while (_channel.Reader.TryRead(out var item))
114 item.Owner.Dispose();
115
116 // complete the channel
117 _channel.Writer.TryComplete();
118 }
119 }
120
121 }
122
123}
Wraps a IBufferWriter<T> and queues data writen to it. Requires disposal to ensure flushing.
AsyncDiagnosticChannelWriter(IBufferWriter< byte > writer)
Initializes a new instance.
void Write(IMemoryOwner< byte > owner, int length)
Enqueues the given memory to be written. Ownership is transfered.