// TODO: Has close() race condition. public unsafe override void Write(byte[] buffer, int offset, int count) { Throw.If.OutOfRange(buffer, offset, count); UpdateSettings(); if (count == 0) { return; } fixed(byte *buffer0 = buffer) { int startTime = Environment.TickCount, writeTimeout = WriteTimeout; for (int bytesWritten = 0; bytesWritten < count;) { int handle = _handle; if (handle < 0) { throw new IOException("Closed."); } var bufferPtr = (IntPtr)(buffer0 + offset + bytesWritten); int bytesToWrite = count - bytesWritten; var fd = new NativeMethods.pollfd() { fd = handle, events = NativeMethods.pollev.OUT }; int ret = NativeMethods.retry(() => NativeMethods.poll(ref fd, 1, GetTimeout(startTime, writeTimeout))); if (ret < 0) { throw new IOException("Write failed (poll)."); } if (ret == 1) { if (fd.revents != NativeMethods.pollev.OUT) { throw new IOException(string.Format("Closed during write ({0}).", fd.revents)); } int writeCount = checked ((int)NativeMethods.retry(() => NativeMethods.write(handle, bufferPtr, (UIntPtr)bytesToWrite))); if (writeCount <= 0 || writeCount > bytesToWrite) { throw new IOException("Write failed."); } bytesWritten += writeCount; } } } }
// TODO: Has close() race condition. public unsafe override int Read(byte[] buffer, int offset, int count) { Throw.If.OutOfRange(buffer, offset, count); UpdateSettings(); if (count == 0) { return(0); } fixed(byte *buffer0 = buffer) { int startTime = Environment.TickCount, readTimeout = ReadTimeout; while (true) { int handle = _handle; if (handle < 0) { throw new IOException("Closed."); } var bufferPtr = (IntPtr)(buffer0 + offset); int bytesToRead = count; var fd = new NativeMethods.pollfd() { fd = handle, events = NativeMethods.pollev.IN }; int ret = NativeMethods.retry(() => NativeMethods.poll(ref fd, 1, GetTimeout(startTime, readTimeout))); if (ret < 0) { throw new IOException("Read failed (poll)."); } if (ret == 1) { if (fd.revents != NativeMethods.pollev.IN) { throw new IOException(string.Format("Closed during read ({0}).", fd.revents)); } int readCount = checked ((int)NativeMethods.retry(() => NativeMethods.read(handle, bufferPtr, (UIntPtr)bytesToRead))); if (readCount <= 0 || readCount > bytesToRead) { throw new IOException("Read failed."); } return(readCount); } } } }