public override int Read([In, Out] byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
if (buffer.Length - offset < count)
throw new ArgumentException(SR.Argument_InvalidOffLen);
Contract.EndContractBlock();
if (!_isOpen) throw new ObjectDisposedException(null, SR.ObjectDisposed_StreamClosed);
if (!CanRead) throw new NotSupportedException(SR.NotSupported_UnreadableStream);
// Use a local variable to avoid a race where another thread
// changes our position after we decide we can read some bytes.
long pos = Interlocked.Read(ref _position);
long len = Interlocked.Read(ref _length);
long n = len - pos;
if (n > count)
n = count;
if (n <= 0)
return 0;
int nInt = (int)n; // Safe because n <= count, which is an Int32
Debug.Assert(pos + nInt >= 0, "_position + n >= 0"); // len is less than 2^63 -1.
unsafe
{
Marshal.Copy((IntPtr)(_mem + pos), buffer, offset, nInt);
}
Interlocked.Exchange(ref _position, pos + n);
return nInt;
}