@@ -56,7 +56,7 @@ public override ValueTask CompleteWritesAsync(CancellationToken cancellationToke
56
56
57
57
private sealed class MemoryConnectionStream : Stream , IGatheringStream
58
58
{
59
- PipeReader _reader ;
59
+ PipeReader ? _reader ;
60
60
PipeWriter ? _writer ;
61
61
62
62
public override bool CanRead => true ;
@@ -77,12 +77,12 @@ public MemoryConnectionStream(PipeReader reader, PipeWriter writer)
77
77
78
78
protected override void Dispose ( bool disposing )
79
79
{
80
- if ( disposing && _writer != null )
80
+ if ( disposing && _reader is PipeReader reader )
81
81
{
82
- _writer . Complete ( ) ;
83
- _reader . Complete ( ) ;
84
- _writer = null ! ;
85
- _reader = null ! ;
82
+ _writer ? . Complete ( ) ;
83
+ reader . Complete ( ) ;
84
+ _writer = null ;
85
+ _reader = null ;
86
86
}
87
87
}
88
88
@@ -106,13 +106,13 @@ public override int Read(byte[] buffer, int offset, int count)
106
106
107
107
public override int Read ( Span < byte > buffer )
108
108
{
109
- if ( _reader == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
109
+ if ( _reader is not PipeReader reader ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
110
110
111
111
try
112
112
{
113
- return FinishRead ( buffer , Tools . BlockForResult ( _reader . ReadAsync ( ) ) ) ;
113
+ return FinishRead ( reader , buffer , Tools . BlockForResult ( _reader . ReadAsync ( ) ) , CancellationToken . None ) ;
114
114
}
115
- catch ( Exception ex )
115
+ catch ( Exception ex ) when ( ex is not OperationCanceledException )
116
116
{
117
117
throw new IOException ( ex . Message , ex ) ;
118
118
}
@@ -129,24 +129,25 @@ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, Cancel
129
129
130
130
public override async ValueTask < int > ReadAsync ( Memory < byte > buffer , CancellationToken cancellationToken = default )
131
131
{
132
- if ( _reader == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
132
+ if ( _reader is not PipeReader reader ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
133
133
134
134
try
135
135
{
136
- ReadResult result = await _reader . ReadAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
137
- return FinishRead ( buffer . Span , result ) ;
136
+ ReadResult result = await reader . ReadAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
137
+ return FinishRead ( reader , buffer . Span , result , cancellationToken ) ;
138
138
}
139
- catch ( Exception ex )
139
+ catch ( Exception ex ) when ( ex is not OperationCanceledException )
140
140
{
141
141
throw new IOException ( ex . Message , ex ) ;
142
142
}
143
143
}
144
144
145
- private int FinishRead ( Span < byte > buffer , in ReadResult result )
145
+ private static int FinishRead ( PipeReader reader , Span < byte > buffer , in ReadResult result , CancellationToken cancellationToken )
146
146
{
147
147
if ( result . IsCanceled )
148
148
{
149
- throw new SocketException ( ( int ) SocketError . OperationAborted ) ;
149
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
150
+ throw new OperationCanceledException ( ) ;
150
151
}
151
152
152
153
ReadOnlySequence < byte > sequence = result . Buffer ;
@@ -171,7 +172,7 @@ private int FinishRead(Span<byte> buffer, in ReadResult result)
171
172
}
172
173
finally
173
174
{
174
- _reader . AdvanceTo ( consumed ) ;
175
+ reader . AdvanceTo ( consumed ) ;
175
176
}
176
177
}
177
178
@@ -180,7 +181,8 @@ public override void Write(byte[] buffer, int offset, int count) =>
180
181
181
182
public override void Write ( ReadOnlySpan < byte > buffer )
182
183
{
183
- if ( _writer == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
184
+ if ( _reader == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
185
+ if ( _writer == null ) throw new InvalidOperationException ( $ "{ nameof ( MemoryConnectionStream ) } cannot be written to after writes have been completed.") ;
184
186
185
187
try
186
188
{
@@ -191,10 +193,10 @@ public override void Write(ReadOnlySpan<byte> buffer)
191
193
192
194
if ( res . IsCanceled )
193
195
{
194
- throw new SocketException ( ( int ) SocketError . OperationAborted ) ;
196
+ throw new OperationCanceledException ( ) ;
195
197
}
196
198
}
197
- catch ( Exception ex )
199
+ catch ( Exception ex ) when ( ex is not OperationCanceledException )
198
200
{
199
201
throw new IOException ( ex . Message , ex ) ;
200
202
}
@@ -205,48 +207,58 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati
205
207
206
208
public override async ValueTask WriteAsync ( ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken = default )
207
209
{
208
- if ( _writer == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
210
+ if ( _reader is null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
211
+ if ( _writer is not PipeWriter writer ) throw new InvalidOperationException ( $ "{ nameof ( MemoryConnectionStream ) } cannot be written to after writes have been completed.") ;
209
212
210
213
try
211
214
{
212
- FlushResult res = await _writer . WriteAsync ( buffer , cancellationToken ) . ConfigureAwait ( false ) ;
215
+ FlushResult res = await writer . WriteAsync ( buffer , cancellationToken ) . ConfigureAwait ( false ) ;
213
216
214
217
if ( res . IsCanceled )
215
218
{
216
- throw new SocketException ( ( int ) SocketError . OperationAborted ) ;
219
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
220
+ throw new OperationCanceledException ( ) ;
217
221
}
218
222
}
219
- catch ( Exception ex )
223
+ catch ( Exception ex ) when ( ex is not OperationCanceledException )
220
224
{
221
225
throw new IOException ( ex . Message , ex ) ;
222
226
}
223
227
}
224
228
225
229
public async ValueTask WriteAsync ( IReadOnlyList < ReadOnlyMemory < byte > > buffers , CancellationToken cancellationToken = default )
226
230
{
227
- if ( _writer == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
231
+ if ( _reader == null ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
232
+ if ( _writer is not PipeWriter writer ) throw new InvalidOperationException ( $ "{ nameof ( MemoryConnectionStream ) } cannot be written to after writes have been completed.") ;
228
233
229
234
try
230
235
{
231
236
foreach ( ReadOnlyMemory < byte > buffer in buffers )
232
237
{
233
- buffer . Span . CopyTo ( _writer . GetSpan ( buffer . Length ) ) ;
234
- _writer . Advance ( buffer . Length ) ;
238
+ buffer . Span . CopyTo ( writer . GetSpan ( buffer . Length ) ) ;
239
+ writer . Advance ( buffer . Length ) ;
235
240
}
236
241
237
- FlushResult res = await _writer . FlushAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
242
+ FlushResult res = await writer . FlushAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
238
243
239
244
if ( res . IsCanceled )
240
245
{
241
- throw new SocketException ( ( int ) SocketError . OperationAborted ) ;
246
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
247
+ throw new OperationCanceledException ( ) ;
242
248
}
243
249
}
244
- catch ( Exception ex )
250
+ catch ( Exception ex ) when ( ex is not OperationCanceledException )
245
251
{
246
252
throw new IOException ( ex . Message , ex ) ;
247
253
}
248
254
}
249
255
256
+ public override IAsyncResult BeginWrite ( byte [ ] buffer , int offset , int count , AsyncCallback ? callback , object ? state ) =>
257
+ TaskToApm . Begin ( WriteAsync ( buffer , offset , count ) , callback , state ) ;
258
+
259
+ public override void EndWrite ( IAsyncResult asyncResult ) =>
260
+ TaskToApm . End ( asyncResult ) ;
261
+
250
262
public override void Flush ( )
251
263
{
252
264
}
@@ -265,6 +277,22 @@ public override void SetLength(long value)
265
277
{
266
278
throw new NotImplementedException ( ) ;
267
279
}
280
+
281
+ public override void CopyTo ( Stream destination , int bufferSize ) =>
282
+ CopyToAsync ( destination , bufferSize , CancellationToken . None ) . GetAwaiter ( ) . GetResult ( ) ;
283
+
284
+ public override async Task CopyToAsync ( Stream destination , int bufferSize , CancellationToken cancellationToken )
285
+ {
286
+ if ( _reader is not PipeReader reader ) throw new ObjectDisposedException ( nameof ( MemoryConnectionStream ) ) ;
287
+ try
288
+ {
289
+ await reader . CopyToAsync ( destination , cancellationToken ) . ConfigureAwait ( false ) ;
290
+ }
291
+ catch ( Exception ex ) when ( ex is not OperationCanceledException )
292
+ {
293
+ throw new IOException ( ex . Message , ex ) ;
294
+ }
295
+ }
268
296
}
269
297
}
270
298
}
0 commit comments