File: System\IO\SyncTextReader.cs
Web Access
Project: src\src\libraries\System.Console\src\System.Console.csproj (System.Console)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
 
namespace System.IO
{
    /* SyncTextReader intentionally locks on itself rather than a private lock object.
     * This is done to synchronize different console readers (https://github.com/dotnet/corefx/pull/2855).
     */
    internal sealed partial class SyncTextReader : TextReader
    {
        internal readonly TextReader _in;
 
        public static SyncTextReader GetSynchronizedTextReader(TextReader reader)
        {
            Debug.Assert(reader != null);
            return reader as SyncTextReader ??
                new SyncTextReader(reader);
        }
 
        internal SyncTextReader(TextReader t)
        {
            _in = t;
        }
 
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                lock (this)
                {
                    _in.Dispose();
                }
            }
        }
 
        public override int Peek()
        {
            lock (this)
            {
                return _in.Peek();
            }
        }
 
        public override int Read()
        {
            lock (this)
            {
                return _in.Read();
            }
        }
 
        public override int Read(char[] buffer, int index, int count)
        {
            lock (this)
            {
                return _in.Read(buffer, index, count);
            }
        }
 
        public override int ReadBlock(char[] buffer, int index, int count)
        {
            lock (this)
            {
                return _in.ReadBlock(buffer, index, count);
            }
        }
 
        public override string? ReadLine()
        {
            lock (this)
            {
                return _in.ReadLine();
            }
        }
 
        public override string ReadToEnd()
        {
            lock (this)
            {
                return _in.ReadToEnd();
            }
        }
 
        //
        // On SyncTextReader all APIs should run synchronously, even the async ones.
        // No explicit locking is needed, as they all just delegate
        //
 
        public override Task<string?> ReadLineAsync()
        {
            return Task.FromResult(ReadLine());
        }
 
        public override ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken)
        {
            return cancellationToken.IsCancellationRequested ?
                ValueTask.FromCanceled<string?>(cancellationToken) :
                new ValueTask<string?>(ReadLine());
        }
 
        public override Task<string> ReadToEndAsync()
        {
            return Task.FromResult(ReadToEnd());
        }
 
        public override Task<string> ReadToEndAsync(CancellationToken cancellationToken)
        {
            return cancellationToken.IsCancellationRequested ?
                Task.FromCanceled<string>(cancellationToken) :
                Task.FromResult(ReadToEnd());
        }
 
        public override Task<int> ReadBlockAsync(char[] buffer, int index, int count)
        {
            ArgumentNullException.ThrowIfNull(buffer);
 
            ArgumentOutOfRangeException.ThrowIfNegative(index);
            ArgumentOutOfRangeException.ThrowIfNegative(count);
            if (buffer.Length - index < count)
                throw new ArgumentException(SR.Argument_InvalidOffLen);
 
            return Task.FromResult(ReadBlock(buffer, index, count));
        }
 
        public override Task<int> ReadAsync(char[] buffer, int index, int count)
        {
            ArgumentNullException.ThrowIfNull(buffer);
 
            ArgumentOutOfRangeException.ThrowIfNegative(index);
            ArgumentOutOfRangeException.ThrowIfNegative(count);
            if (buffer.Length - index < count)
                throw new ArgumentException(SR.Argument_InvalidOffLen);
 
            return Task.FromResult(Read(buffer, index, count));
        }
    }
}