// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //============================================================ // // Class: Stream // // Purpose: Abstract base class for all Streams. Provides // default implementations of asynchronous reads & writes, in // terms of the synchronous reads & writes (and vice versa). // //=========================================================== using System; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; namespace System.IO { //| [CCtorIsRunDuringStartup] public abstract class Stream : IDisposable { //| public static readonly Stream Null = new NullStream(); //| public abstract bool CanRead { get; } // If CanSeek is false, Position, Seek, Length, and SetLength should throw. //| public abstract bool CanSeek { get; } //| public abstract bool CanWrite { get; } //| public abstract long Length { get; } //| public abstract long Position { get; set; } //| public virtual void Close() { } //| /// void IDisposable.Dispose() { Close(); } //| public abstract void Flush(); //| [CLSCompliant(false)] protected virtual WaitHandle CreateWaitHandle() { return new ManualResetEvent(false); } //| public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object _state) { if (!CanRead) __Error.ReadNotSupported(); // To avoid a race with a stream's position pointer & generating race // conditions with internal buffer indexes in our own streams that // don't natively support async IO operations when there are multiple // async requests outstanding, we will block the application's main // thread and do the IO synchronously. SynchronousAsyncResult asyncResult = new SynchronousAsyncResult(_state, false); try { int numRead = Read(buffer, offset, count); asyncResult._numRead = numRead; asyncResult._isCompleted = true; asyncResult._waitHandle.Set(); } catch (IOException e) { asyncResult._exception = e; } if (callback != null) callback(asyncResult); return asyncResult; } //| public virtual int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException("asyncResult"); SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult; if (ar == null || ar.IsWrite) { __Error.WrongAsyncResult(); assume false; // never gets here } if (ar._EndXxxCalled) { __Error.EndReadCalledTwice(); assume false; // never gets here } ar._EndXxxCalled = true; if (ar._exception != null) throw ar._exception; return ar._numRead; } //| public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object _state) { if (!CanWrite) __Error.WriteNotSupported(); // To avoid a race with a stream's position pointer & generating race // conditions with internal buffer indexes in our own streams that // don't natively support async IO operations when there are multiple // async requests outstanding, we will block the application's main // thread and do the IO synchronously. SynchronousAsyncResult asyncResult = new SynchronousAsyncResult(_state, true); try { Write(buffer, offset, count); asyncResult._isCompleted = true; asyncResult._waitHandle.Set(); } catch (IOException e) { asyncResult._exception = e; } if (callback != null) callback.BeginInvoke(asyncResult, null, null); return asyncResult; } //| public virtual void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException("asyncResult"); SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult; if (ar == null || !ar.IsWrite) { __Error.WrongAsyncResult(); assume false; // never gets here } if (ar._EndXxxCalled) { __Error.EndWriteCalledTwice(); assume false; // never gets here } ar._EndXxxCalled = true; if (ar._exception != null) throw ar._exception; } //| public abstract long Seek(long offset, SeekOrigin origin); //| public abstract void SetLength(long value); //| public abstract int Read([In, Out] byte[] buffer, int offset, int count); //| public virtual int ReadByte() { // Reads one byte from the stream by calling Read(byte[], int, int). // Will return an unsigned byte cast to an int or -1 on end of stream. // The performance of the default implementation on Stream is bad, // and any subclass with an internal buffer should override this method. byte[] oneByteArray = new byte[1]; int r = Read(oneByteArray, 0, 1); if (r == 0) return -1; return oneByteArray[0]; } //| public abstract void Write(byte[] buffer, int offset, int count); //| public virtual void WriteByte(byte value) { // Writes one byte from the stream by calling Write(byte[], int, int). // The performance of the default implementation on Stream is bad, // and any subclass with an internal buffer should override this method. byte[] oneByteArray = new byte[1]; oneByteArray[0] = value; Write(oneByteArray, 0, 1); } // No data, no need to serialize private class NullStream : Stream { protected internal NullStream() {} //| public override bool CanRead { get { return true; } } //| public override bool CanWrite { get { return true; } } //| public override bool CanSeek { get { return true; } } //| public override long Length { get { return 0; } } //| public override long Position { get { return 0; } set {} } public override void Close() { } public override void Flush() { } public override int Read([In, Out] byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long length) { } } // Used as the IAsyncResult object when using asynchronous IO methods // on the base Stream class. Note I'm not using async delegates, so // this is necessary. private sealed class SynchronousAsyncResult : IAsyncResult { internal ManualResetEvent _waitHandle; internal Object _stateObject; internal int _numRead; internal bool _isCompleted; internal bool _isWrite; internal bool _EndXxxCalled; internal Exception _exception; internal SynchronousAsyncResult(Object asyncStateObject, bool isWrite) { _stateObject = asyncStateObject; _isWrite = isWrite; _waitHandle = new ManualResetEvent(false); } public bool IsCompleted { get { return _isCompleted; } } public WaitHandle AsyncWaitHandle { get { return _waitHandle; } } public Object AsyncState { get { return _stateObject; } } public bool CompletedSynchronously { get { return true; } } internal bool IsWrite { get { return _isWrite; } } } } }