|
|
|
@ -197,7 +197,7 @@ bufferediobase_write(PyObject *self, PyObject *args) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
typedef struct _buffered { |
|
|
|
typedef struct { |
|
|
|
PyObject_HEAD |
|
|
|
|
|
|
|
PyObject *raw; |
|
|
|
@ -239,18 +239,8 @@ typedef struct _buffered { |
|
|
|
|
|
|
|
PyObject *dict; |
|
|
|
PyObject *weakreflist; |
|
|
|
|
|
|
|
/* a doubly-linked chained list of "buffered" objects that need to |
|
|
|
be flushed when the process exits */ |
|
|
|
struct _buffered *next, *prev; |
|
|
|
} buffered; |
|
|
|
|
|
|
|
/* the actual list of buffered objects */ |
|
|
|
static buffered buffer_list_end = { |
|
|
|
.next = &buffer_list_end, |
|
|
|
.prev = &buffer_list_end |
|
|
|
}; |
|
|
|
|
|
|
|
/* |
|
|
|
Implementation notes: |
|
|
|
|
|
|
|
@ -389,21 +379,10 @@ _enter_buffered_busy(buffered *self) |
|
|
|
(self->buffer_size * (size / self->buffer_size))) |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
remove_from_linked_list(buffered *self) |
|
|
|
{ |
|
|
|
self->next->prev = self->prev; |
|
|
|
self->prev->next = self->next; |
|
|
|
self->prev = NULL; |
|
|
|
self->next = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
buffered_dealloc(buffered *self) |
|
|
|
{ |
|
|
|
self->finalizing = 1; |
|
|
|
if (self->next != NULL) |
|
|
|
remove_from_linked_list(self); |
|
|
|
if (_PyIOBase_finalize((PyObject *) self) < 0) |
|
|
|
return; |
|
|
|
_PyObject_GC_UNTRACK(self); |
|
|
|
@ -1827,38 +1806,10 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, |
|
|
|
self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type && |
|
|
|
Py_TYPE(raw) == &PyFileIO_Type); |
|
|
|
|
|
|
|
if (self->next == NULL) { |
|
|
|
self->prev = &buffer_list_end; |
|
|
|
self->next = buffer_list_end.next; |
|
|
|
buffer_list_end.next->prev = self; |
|
|
|
buffer_list_end.next = self; |
|
|
|
} |
|
|
|
|
|
|
|
self->ok = 1; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* Ensure all buffered writers are flushed before proceeding with |
|
|
|
* normal shutdown. Otherwise, if the underlying file objects get |
|
|
|
* finalized before the buffered writer wrapping it then any buffered |
|
|
|
* data will be lost. |
|
|
|
*/ |
|
|
|
void _PyIO_atexit_flush(void) |
|
|
|
{ |
|
|
|
while (buffer_list_end.next != &buffer_list_end) { |
|
|
|
buffered *buf = buffer_list_end.next; |
|
|
|
remove_from_linked_list(buf); |
|
|
|
if (buf->ok && !buf->finalizing) { |
|
|
|
/* good state and not finalizing */ |
|
|
|
Py_INCREF(buf); |
|
|
|
buffered_flush(buf, NULL); |
|
|
|
Py_DECREF(buf); |
|
|
|
PyErr_Clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static Py_ssize_t |
|
|
|
_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len) |
|
|
|
{ |
|
|
|
|