mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 01:50:53 +09:00
Replace custom synchronized text writer (dotnet/corefx#30796)
TextWriter.Synchronized does this and isn't missing APIs, which can cause derived methods to not be called. Test added.
Commit migrated from 0b868a47b4
This commit is contained in:
parent
4d3212d7c3
commit
1052b59792
5 changed files with 30 additions and 394 deletions
|
@ -13,39 +13,6 @@ using System.Diagnostics.CodeAnalysis;
|
|||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#ReadToEnd():System.String")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#ReadKey(System.Boolean&):System.ConsoleKeyInfo")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#get_KeyAvailable():System.Boolean")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#get_NewLine():System.String")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#set_NewLine(System.String)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Dispose(System.Boolean)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Flush()")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Char)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Char[])")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Char[],System.Int32,System.Int32)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Boolean)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Int32)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.UInt32)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Int64)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.UInt64)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Single)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Double)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Decimal)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.String)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Object)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.String,System.Object[])")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine()")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Char)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Char[])")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Char[],System.Int32,System.Int32)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Boolean)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Int32)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.UInt32)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Int64)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.UInt64)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Single)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Double)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Decimal)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.String)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Object)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.String,System.Object[])")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#ResetColor()")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#GetCursorPosition(System.Int32&,System.Int32&)")]
|
||||
[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#RefreshColors(System.ConsoleColor&,System.ConsoleColor)")]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
|
||||
<PropertyGroup>
|
||||
|
@ -26,7 +26,6 @@
|
|||
<Compile Include="System\ConsoleModifiers.cs" />
|
||||
<Compile Include="System\IO\ConsoleStream.cs" />
|
||||
<Compile Include="System\IO\SyncTextReader.cs" />
|
||||
<Compile Include="System\IO\SyncTextWriter.cs" />
|
||||
<Compile Include="System\IO\Error.cs" />
|
||||
<Compile Include="$(CommonPath)\System\Text\ConsoleEncoding.cs">
|
||||
<Link>Common\System\Text\ConsoleEncoding.cs</Link>
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace System
|
|||
|
||||
private static TextWriter CreateOutputWriter(Stream outputStream)
|
||||
{
|
||||
return SyncTextWriter.GetSynchronizedTextWriter(outputStream == Stream.Null ?
|
||||
return TextWriter.Synchronized(outputStream == Stream.Null ?
|
||||
StreamWriter.Null :
|
||||
new StreamWriter(
|
||||
stream: outputStream,
|
||||
|
@ -408,7 +408,7 @@ namespace System
|
|||
public static void SetOut(TextWriter newOut)
|
||||
{
|
||||
CheckNonNull(newOut, nameof(newOut));
|
||||
newOut = SyncTextWriter.GetSynchronizedTextWriter(newOut);
|
||||
newOut = TextWriter.Synchronized(newOut);
|
||||
Volatile.Write(ref s_isOutTextWriterRedirected, true);
|
||||
|
||||
lock (InternalSyncObject)
|
||||
|
@ -420,7 +420,7 @@ namespace System
|
|||
public static void SetError(TextWriter newError)
|
||||
{
|
||||
CheckNonNull(newError, nameof(newError));
|
||||
newError = SyncTextWriter.GetSynchronizedTextWriter(newError);
|
||||
newError = TextWriter.Synchronized(newError);
|
||||
Volatile.Write(ref s_isErrorTextWriterRedirected, true);
|
||||
|
||||
lock (InternalSyncObject)
|
||||
|
|
|
@ -1,346 +0,0 @@
|
|||
// 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.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
/* SyncTextWriter intentionally locks on itself rather than a private lock object.
|
||||
* This is done to synchronize different console writers.
|
||||
* For example - colored console writers can be synchronized with non-colored
|
||||
* writers by locking on Console.On (Issue#2855).
|
||||
*/
|
||||
internal sealed class SyncTextWriter : TextWriter, IDisposable
|
||||
{
|
||||
internal readonly TextWriter _out;
|
||||
|
||||
internal static SyncTextWriter GetSynchronizedTextWriter(TextWriter writer)
|
||||
{
|
||||
Debug.Assert(writer != null);
|
||||
return writer as SyncTextWriter ??
|
||||
new SyncTextWriter(writer);
|
||||
}
|
||||
|
||||
internal SyncTextWriter(TextWriter t)
|
||||
: base(t.FormatProvider)
|
||||
{
|
||||
_out = t;
|
||||
}
|
||||
|
||||
public override Encoding Encoding
|
||||
{
|
||||
get { return _out.Encoding; }
|
||||
}
|
||||
|
||||
public override IFormatProvider FormatProvider
|
||||
{
|
||||
get { return _out.FormatProvider; }
|
||||
}
|
||||
|
||||
public override string NewLine
|
||||
{
|
||||
get { lock (this) { return _out.NewLine; } }
|
||||
set { lock (this) { _out.NewLine = value; } }
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(char value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(char[] buffer)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(char[] buffer, int index, int count)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(buffer, index, count);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(bool value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(int value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(uint value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(long value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(ulong value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(float value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(double value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(decimal value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(string value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(object value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(string format, object[] arg)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.Write(format, arg);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(char value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(decimal value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(char[] buffer)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(char[] buffer, int index, int count)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(buffer, index, count);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(bool value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(int value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(uint value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(long value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(ulong value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(float value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(double value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(string value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(object value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteLine(string format, object[] arg)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
_out.WriteLine(format, arg);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// On SyncTextWriter all APIs should run synchronously, even the async ones.
|
||||
//
|
||||
|
||||
public override Task WriteAsync(char value)
|
||||
{
|
||||
Write(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task WriteAsync(string value)
|
||||
{
|
||||
Write(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task WriteAsync(char[] buffer, int index, int count)
|
||||
{
|
||||
Write(buffer, index, count);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task WriteLineAsync(char value)
|
||||
{
|
||||
WriteLine(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task WriteLineAsync(string value)
|
||||
{
|
||||
WriteLine(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task WriteLineAsync(char[] buffer, int index, int count)
|
||||
{
|
||||
WriteLine(buffer, index, count);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task FlushAsync()
|
||||
{
|
||||
Flush();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
@ -11,7 +13,6 @@ using Xunit;
|
|||
|
||||
public class SyncTextWriter
|
||||
{
|
||||
|
||||
[Fact]
|
||||
public void SyncTextWriterLockedOnThis()
|
||||
{
|
||||
|
@ -22,14 +23,16 @@ public class SyncTextWriter
|
|||
Console.SetOut(newWriter);
|
||||
TextWriter syncWriter = Console.Out;
|
||||
|
||||
bool called = false;
|
||||
newWriter.Callback = _ =>
|
||||
newWriter.Callback = () =>
|
||||
{
|
||||
Assert.True(Monitor.IsEntered(syncWriter));
|
||||
called = true;
|
||||
};
|
||||
Console.Write("c");
|
||||
Assert.True(called);
|
||||
Assert.True(newWriter.WriteCharCalled);
|
||||
|
||||
Console.Write("{0}", 32);
|
||||
Assert.True(newWriter.WriteFormatCalled);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -39,11 +42,24 @@ public class SyncTextWriter
|
|||
|
||||
private sealed class CallbackTextWriter : TextWriter
|
||||
{
|
||||
internal Action<char> Callback;
|
||||
internal Action Callback;
|
||||
|
||||
public bool WriteCharCalled;
|
||||
public bool WriteFormatCalled;
|
||||
|
||||
|
||||
public override Encoding Encoding { get { return Encoding.UTF8; } }
|
||||
|
||||
public override void Write(char value) { Callback(value); }
|
||||
public override void Write(char value)
|
||||
{
|
||||
WriteCharCalled = true;
|
||||
Callback();
|
||||
}
|
||||
|
||||
public override void Write(string format, object arg0)
|
||||
{
|
||||
WriteFormatCalled = true;
|
||||
Callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue