Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement IAsyncDisposable for XmlWriter #35233

Merged
merged 14 commits into from
Apr 28, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,8 @@ public async Task SaveAsync(Stream stream, SaveOptions options, CancellationToke
}
}

using (XmlWriter w = XmlWriter.Create(stream, ws))
XmlWriter w = XmlWriter.Create(stream, ws);
await using (w.ConfigureAwait(false))
{
await WriteToAsync(w, cancellationToken).ConfigureAwait(false);
await w.FlushAsync().ConfigureAwait(false);
Expand Down Expand Up @@ -706,7 +707,8 @@ public async Task SaveAsync(TextWriter textWriter, SaveOptions options, Cancella

ws.Async = true;

using (XmlWriter w = XmlWriter.Create(textWriter, ws))
XmlWriter w = XmlWriter.Create(textWriter, ws);
await using (w.ConfigureAwait(false))
{
await WriteToAsync(w, cancellationToken).ConfigureAwait(false);
await w.FlushAsync().ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,8 @@ public async Task SaveAsync(Stream stream, SaveOptions options, CancellationToke

ws.Async = true;

using (XmlWriter w = XmlWriter.Create(stream, ws))
XmlWriter w = XmlWriter.Create(stream, ws);
await using (w.ConfigureAwait(false))
{
await SaveAsync(w, cancellationToken).ConfigureAwait(false);
}
Expand Down Expand Up @@ -1141,7 +1142,8 @@ public async Task SaveAsync(TextWriter textWriter, SaveOptions options, Cancella

ws.Async = true;

using (XmlWriter w = XmlWriter.Create(textWriter, ws))
XmlWriter w = XmlWriter.Create(textWriter, ws);
await using (w.ConfigureAwait(false))
{
await SaveAsync(w, cancellationToken).ConfigureAwait(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,69 @@ public static IEnumerable<object[]> RoundtripOptions_MemberData
}
}

public static IEnumerable<object[]> IsAsync_SaveOptions_Data
{
get
{
foreach (bool isAsync in new[] { true, false })
foreach (SaveOptions saveOptions in Enum.GetValues(typeof(SaveOptions)))
yield return new object[] { isAsync, saveOptions };
}
}

[Theory]
[MemberData(nameof(IsAsync_SaveOptions_Data))]
public async Task SaveAsync_CallsAsyncOnly_SaveSync_CallsSyncOnly(bool isAsync, SaveOptions saveOptions)
{
XDocument document = XDocument.Parse("<root>Test document async save</root>");
var element = new XElement("Test");
using (ForceSyncAsyncStream stream = new ForceSyncAsyncStream(isAsync))
{
if (isAsync)
{
await document.SaveAsync(stream, saveOptions, CancellationToken.None);
await element.SaveAsync(stream, saveOptions, CancellationToken.None);
}
else
{
document.Save(stream);
element.Save(stream);
}
}
}
}

public class ForceSyncAsyncStream : MemoryStream
{
private bool _isAsync;

public ForceSyncAsyncStream(bool async)
{
_isAsync = async;
}
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved

public override void Flush()
{
Assert.False(_isAsync, "Sync operation not allowed");
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
base.Flush();
}

public override Task FlushAsync(CancellationToken cancellationToken)
{
Assert.True(_isAsync, "Async operation not allowed");
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
return Task.CompletedTask;
}

public override void Write(byte[] buffer, int offset, int count)
{
Assert.False(_isAsync, "Sync operation not allowed");
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
base.Write(buffer, offset, count);
}

public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
Assert.True(_isAsync, "Async operation not allowed");
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
return Task.CompletedTask;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,13 @@ public override Task WriteNodeAsync(XPathNavigator navigator, bool defattr)
_lastTask = task;
return task;
}

protected override ValueTask DisposeAsyncCore()
{
CheckAsync();
return _coreWriter.DisposeAsync();
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -823,8 +823,11 @@ protected virtual void FlushBuffer()
}
else
{
// Write text to TextWriter
writer.Write(bufChars, 1, bufPos - 1);
if (bufPos - 1 > 0)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
// Write text to TextWriter
writer.Write(bufChars, 1, bufPos - 1);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,62 @@ internal override Task WriteXmlDeclarationAsync(string xmldecl)
return Task.CompletedTask;
}

protected override async ValueTask DisposeAsyncCore()
{
try
{
await FlushBufferAsync().ConfigureAwait(false);
}
finally
{
// Future calls to Close or Flush shouldn't write to Stream or Writer
writeToNull = true;

if (stream != null)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
try
{
await stream.FlushAsync().ConfigureAwait(false);
}
finally
{
try
{
if (closeOutput)
{
await stream.DisposeAsync().ConfigureAwait(false);
}
}
finally
{
stream = null;
}
}
}
else if (writer != null)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
krwq marked this conversation as resolved.
Show resolved Hide resolved
{
try
{
await writer.FlushAsync().ConfigureAwait(false);
}
finally
{
try
{
if (closeOutput)
{
await writer.DisposeAsync().ConfigureAwait(false);
}
}
finally
{
writer = null;
}
}
}
}
}

// Serialize the document type declaration.
public override async Task WriteDocTypeAsync(string name, string pubid, string sysid, string subset)
{
Expand Down Expand Up @@ -586,8 +642,11 @@ protected virtual async Task FlushBufferAsync()
}
else
{
// Write text to TextWriter
await writer.WriteAsync(bufChars, 1, bufPos - 1).ConfigureAwait(false);
if (bufPos - 1 > 0)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
// Write text to TextWriter
await writer.WriteAsync(bufChars, 1, bufPos - 1).ConfigureAwait(false);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -820,8 +820,11 @@ namespace System.Xml
if (!writeToNull)
{
<# if (WriterType == RawTextWriterType.Utf8) { #>
Debug.Assert(stream != null);
stream.Write(<#= BufferName #>, 1, bufPos - 1);
if (bufPos - 1 > 0)
{
Debug.Assert(stream != null);
stream.Write(<#= BufferName #>, 1, bufPos - 1);
}
<# } else { #>
Debug.Assert(stream != null || writer != null);

Expand Down Expand Up @@ -849,8 +852,11 @@ namespace System.Xml
}
else
{
// Write text to TextWriter
writer.Write(<#= BufferName #>, 1, bufPos - 1);
if (bufPos - 1 > 0)
{
// Write text to TextWriter
writer.Write(<#= BufferName #>, 1, bufPos - 1);
}
}
<# } #>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,64 @@ namespace System.Xml
return Task.CompletedTask;
}

protected override async ValueTask DisposeAsyncCore()
{
try
{
await FlushBufferAsync().ConfigureAwait(false);
}
finally
{
// Future calls to Close or Flush shouldn't write to Stream or Writer
writeToNull = true;

if (stream != null)
{
try
{
await stream.FlushAsync().ConfigureAwait(false);
}
finally
{
try
{
if (closeOutput)
{
await stream.DisposeAsync().ConfigureAwait(false);
}
}
finally
{
stream = null;
}
}
}
<# if (WriterType == RawTextWriterType.Encoded) { #>
else if (writer != null)
{
try
{
await writer.FlushAsync().ConfigureAwait(false);
}
finally
{
try
{
if (closeOutput)
{
await writer.DisposeAsync().ConfigureAwait(false);
}
}
finally
{
writer = null;
}
}
}
<# } #>
}
}

// Serialize the document type declaration.
public override async Task WriteDocTypeAsync(string name, string pubid, string sysid, string subset)
{
Expand Down Expand Up @@ -563,8 +621,11 @@ namespace System.Xml
if (!writeToNull)
{
<# if (WriterType == RawTextWriterType.Utf8) { #>
Debug.Assert(stream != null);
await stream.WriteAsync(bufBytes, 1, bufPos - 1).ConfigureAwait(false);
if (bufPos - 1 > 0)
{
Debug.Assert(stream != null);
await stream.WriteAsync(bufBytes, 1, bufPos - 1).ConfigureAwait(false);
}
<# } else { #>
Debug.Assert(stream != null || writer != null);

Expand Down Expand Up @@ -592,8 +653,11 @@ namespace System.Xml
}
else
{
// Write text to TextWriter
await writer.WriteAsync(<#= BufferName #>, 1, bufPos - 1).ConfigureAwait(false);
if (bufPos - 1 > 0)
{
// Write text to TextWriter
await writer.WriteAsync(<#= BufferName #>, 1, bufPos - 1).ConfigureAwait(false);
}
}
<# } #>
}
Expand Down Expand Up @@ -689,7 +753,7 @@ namespace System.Xml
<#= BufferType #>* pDst = pDstBegin + bufPos;

int ch = 0;
for (;;)
while (true)
{
<#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
if (pDstEnd > pDstBegin + bufLen)
Expand Down Expand Up @@ -879,7 +943,7 @@ namespace System.Xml
<#= BufferType #>* pDst = pDstBegin + bufPos;

int ch = 0;
for (;;)
while (true)
{
<#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
if (pDstEnd > pDstBegin + bufLen)
Expand Down Expand Up @@ -1105,7 +1169,7 @@ namespace System.Xml
char* pSrc = pSrcBegin;

int ch = 0;
for (;;)
while (true)
{
<#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
if (pDstEnd > pDstBegin + bufLen)
Expand Down Expand Up @@ -1266,7 +1330,7 @@ namespace System.Xml
<#= BufferType #>* pDst = pDstBegin + bufPos;

int ch = 0;
for (;;)
while (true)
{
<#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
if (pDstEnd > pDstBegin + bufLen)
Expand Down Expand Up @@ -1454,7 +1518,7 @@ namespace System.Xml
<#= BufferType #>* pDst = pDstBegin + bufPos;

int ch = 0;
for (;;)
while (true)
{
<#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
if (pDstEnd > pDstBegin + bufLen)
Expand Down Expand Up @@ -1630,7 +1694,7 @@ namespace System.Xml
<#= BufferType #>* pDst = pDstBegin + bufPos;

int ch = 0;
for (;;)
while (true)
{
<#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
if (pDstEnd > pDstBegin + bufLen)
Expand Down
Loading