-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Add initial async iterators support to System.Private.CoreLib #20442
Changes from all commits
79d58f1
1e864d0
5f15a18
6513f53
734e176
aa0e244
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
namespace System.Collections.Generic | ||
{ | ||
public interface IAsyncEnumerable<out T> | ||
{ | ||
IAsyncEnumerator<T> GetAsyncEnumerator(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Threading.Tasks; | ||
|
||
namespace System.Collections.Generic | ||
{ | ||
public interface IAsyncEnumerator<out T> : IAsyncDisposable | ||
{ | ||
ValueTask<bool> MoveNextAsync(); | ||
T Current { get; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Threading.Tasks; | ||
|
||
namespace System | ||
{ | ||
public interface IAsyncDisposable | ||
{ | ||
ValueTask DisposeAsync(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -195,32 +195,67 @@ protected override void Dispose(bool disposing) | |
} | ||
finally | ||
{ | ||
// Dispose of our resources if this StreamWriter is closable. | ||
// Note: Console.Out and other such non closable streamwriters should be left alone | ||
if (!LeaveOpen && _stream != null) | ||
CloseStreamFromDispose(disposing); | ||
} | ||
} | ||
|
||
private void CloseStreamFromDispose(bool disposing) | ||
{ | ||
// Dispose of our resources if this StreamWriter is closable. | ||
if (!LeaveOpen && _stream != null) | ||
{ | ||
try | ||
{ | ||
try | ||
{ | ||
// Attempt to close the stream even if there was an IO error from Flushing. | ||
// Note that Stream.Close() can potentially throw here (may or may not be | ||
// due to the same Flush error). In this case, we still need to ensure | ||
// cleaning up internal resources, hence the finally block. | ||
if (disposing) | ||
{ | ||
_stream.Close(); | ||
} | ||
} | ||
finally | ||
// Attempt to close the stream even if there was an IO error from Flushing. | ||
// Note that Stream.Close() can potentially throw here (may or may not be | ||
// due to the same Flush error). In this case, we still need to ensure | ||
// cleaning up internal resources, hence the finally block. | ||
if (disposing) | ||
{ | ||
_stream = null; | ||
_byteBuffer = null; | ||
_charBuffer = null; | ||
_encoding = null; | ||
_encoder = null; | ||
_charLen = 0; | ||
base.Dispose(disposing); | ||
_stream.Close(); | ||
} | ||
} | ||
finally | ||
{ | ||
_stream = null; | ||
_byteBuffer = null; | ||
_charBuffer = null; | ||
_encoding = null; | ||
_encoder = null; | ||
_charLen = 0; | ||
base.Dispose(disposing); | ||
} | ||
} | ||
} | ||
|
||
public override ValueTask DisposeAsync() | ||
{ | ||
if (GetType() != typeof(StreamWriter)) | ||
{ | ||
// Since this is a derived StreamWriter, delegate to whatever logic | ||
// the derived implementation already has in Dispose. | ||
return new ValueTask(Task.Factory.StartNew(s => ((StreamWriter)s).Dispose(), this, | ||
CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)); | ||
} | ||
|
||
return DisposeAsyncCore(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I'm not quite following you. No exceptions should escape here: if any occur inside DisposeAsyncCore, they'll be stored into the ValueTask that's returned, which presumably is the behavior we'd want. I have been debating with myself the larger question about whether exceptions should be valid at all. In general Dispose isn't supposed to throw, and thus DisposeAsync shouldn't either (or return a ValueTask that might fault with an exception), but in cases where an implementation's Dispose is already throwing, it seems reasonable to keep parity on the DisposeAsync, rather than eating the exceptions in cases where they wouldn't be eaten in Dispose. Opinion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ugg ... I missed that Yeah I agree that no exceptions is a great principal but reality doesn't always line up with it. |
||
} | ||
|
||
private async ValueTask DisposeAsyncCore() | ||
{ | ||
Debug.Assert(GetType() == typeof(StreamWriter)); | ||
|
||
// Same logic as in Dispose(true), but async. | ||
try | ||
{ | ||
if (_stream != null) | ||
{ | ||
await FlushAsync().ConfigureAwait(false); | ||
} | ||
} | ||
finally | ||
{ | ||
CloseStreamFromDispose(disposing: true); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what level of xml doc is expected. Consider adding (here and other public types).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll add 'em.