Skip to main content

Modules/_io/bufferedio.c (part 2)

cpython 3.14 @ ab2d84fe1023/Modules/_io/bufferedio.c

This annotation covers the write path and readline in Modules/_io/bufferedio.c. For the BufferedReader read path, the internal lock, and the _io module structure see the module_io_iobase_c annotation.

Map

LinesSymbolRole
1-400BufferedWriter.writeBuffer fill and flush trigger
401-700BufferedWriter.flushDrain to underlying raw stream with retry
701-950BufferedRWPairNon-seekable read+write buffer over two raw streams
951-1200BufferedRandomSeekable read/write buffer
1201-2800readline lock-free pathRead until \n without acquiring the full buffer lock

Reading

BufferedWriter.write

write(b) appends bytes to self.buffer. When the buffer reaches buffer_size, it calls self.raw.write(self.buffer) to flush. If the raw write is non-blocking and raises BlockingIOError, the unwritten bytes are stored and write returns the number of bytes accepted.

// CPython: Modules/_io/bufferedio.c:1840 buffered_write
static PyObject *
buffered_write(buffered *self, PyObject *args)
{
Py_buffer data;
...
if (VALID_WRITE_BUFFER(self) &&
self->readable_pos == self->write_pos) {
/* fast path: append to existing buffer */
...
}
if (avail + written < data.len) {
/* buffer full: flush first */
...
}
}

readline fast path

readline() scans the read buffer for \n without acquiring the write lock. If found, it slices the buffer and returns immediately. Only if a \n is not in the buffer does it fall through to the full _readahead path.

_io.DEFAULT_BUFFER_SIZE

The default is 8192 bytes on all platforms. io.open uses this when buffering=-1 (the default). Buffer size can be changed by passing an explicit integer to open(buffering=N).

BufferedRWPair

BufferedRWPair wraps two separate raw streams (one readable, one writable) into a single buffered object. It is used by socket.makefile() when a socket is opened in both read and write mode.

gopy notes

The gopy io layer wraps Go's io.Reader/io.Writer interfaces. BufferedWriter maps to bufio.Writer. The readline scan loop is not yet implemented; gopy's readline falls back to byte-by-byte reading.