public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) { if (array == null) { throw new ArgumentNullException("array"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", Helper.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (numBytes < 0) { throw new ArgumentOutOfRangeException("numBytes", Helper.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (array.Length - offset < numBytes) { throw new ArgumentException(Helper.GetResourceString("Argument_InvalidOffLen")); } if (!CanWrite) { __Error.WriteNotSupported(); } Debug.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both."); if (_writePos == 0) { if (_readPos < _readLen) { FlushRead(); } _readPos = 0; _readLen = 0; } int n = bufferSize - _writePos; if (numBytes <= n) { if (_buffer == null) { _buffer = new byte[bufferSize]; } Buffer.BlockCopy(array, offset, _buffer, _writePos, numBytes); _writePos += numBytes; return(BufferedStreamAsyncResult.Complete(numBytes, userCallback, stateObject, true)); } if (_writePos > 0) { FlushWrite(false); } return(BeginWriteCore(array, offset, numBytes, userCallback, stateObject)); }
public unsafe override void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } BufferedStreamAsyncResult bsar = asyncResult as BufferedStreamAsyncResult; if (bsar == null) { EndWriteCore(asyncResult); } }
internal static IAsyncResult Complete(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject, bool isWrite) { // Fake async BufferedStreamAsyncResult asyncResult = new BufferedStreamAsyncResult(); asyncResult._numBytes = numBufferedBytes; asyncResult._userCallback = userCallback; asyncResult._userStateObject = userStateObject; asyncResult._isWrite = isWrite; if (userCallback != null) { userCallback(asyncResult); } return(asyncResult); }
public unsafe override int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } BufferedStreamAsyncResult bsar = asyncResult as BufferedStreamAsyncResult; if (bsar != null) { if (bsar._isWrite) { __Error.WrongAsyncResult(); } return(bsar._numBytes); } else { return(EndReadCore(asyncResult)); } }
internal static IAsyncResult Complete(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject, bool isWrite) { // Fake async BufferedStreamAsyncResult asyncResult = new BufferedStreamAsyncResult(); asyncResult._numBytes = numBufferedBytes; asyncResult._userCallback = userCallback; asyncResult._userStateObject = userStateObject; asyncResult._isWrite = isWrite; if (userCallback != null) { userCallback(asyncResult); } return asyncResult; }
public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) { if (array == null) { throw new ArgumentNullException("array"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", Helper.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (numBytes < 0) { throw new ArgumentOutOfRangeException("numBytes", Helper.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (array.Length - offset < numBytes) { throw new ArgumentException(Helper.GetResourceString("Argument_InvalidOffLen")); } if (!CanRead) { __Error.ReadNotSupported(); } Debug.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both."); if (_writePos > 0) { FlushWrite(false); } if (_readPos == _readLen) { // I can't see how to handle buffering of async requests when // filling the buffer asynchronously, without a lot of complexity. // The problems I see are issuing an async read, we do an async // read to fill the buffer, then someone issues another read // (either synchronously or asynchronously) before the first one // returns. This would involve some sort of complex buffer locking // that we probably don't want to get into, at least not in V1. // If we did a sync read to fill the buffer, we could avoid the // problem, and any async read less than 64K gets turned into a // synchronous read by NT anyways... -- if (numBytes < bufferSize) { if (_buffer == null) { _buffer = new byte[bufferSize]; } IAsyncResult bufferRead = BeginReadCore(_buffer, 0, bufferSize, null, null, 0); _readLen = EndRead(bufferRead); int n = _readLen; if (n > numBytes) { n = numBytes; } Buffer.BlockCopy(_buffer, 0, array, offset, n); _readPos = n; // Fake async return(BufferedStreamAsyncResult.Complete(n, userCallback, stateObject, false)); } // Here we're making our position pointer inconsistent // with our read buffer. Throw away the read buffer's contents. _readPos = 0; _readLen = 0; return(BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0)); } else { int n = _readLen - _readPos; if (n > numBytes) { n = numBytes; } Buffer.BlockCopy(_buffer, _readPos, array, offset, n); _readPos += n; if (n >= numBytes) { return(BufferedStreamAsyncResult.Complete(n, userCallback, stateObject, false)); } // For streams with no clear EOF like serial ports or pipes // we cannot read more data without causing an app to block // incorrectly. Pipes don't go down this path // though. This code needs to be fixed. // Throw away read buffer. _readPos = 0; _readLen = 0; // WARNING: all state on asyncResult objects must be set before // we call ReadFile in BeginReadCore, since the OS can run our // callback & the user's callback before ReadFile returns. return(BeginReadCore(array, offset + n, numBytes - n, userCallback, stateObject, n)); } }