Skip to content

Commit a83cf1f

Browse files
WIP module state / multi-phase init
1 parent 0328a34 commit a83cf1f

File tree

14 files changed

+465
-251
lines changed

14 files changed

+465
-251
lines changed

Modules/_io/_iomodule.c

Lines changed: 97 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
386386
return result;
387387
}
388388

389-
_PyIO_State *state = IO_STATE();
389+
_PyIO_State *state = get_io_state(module);
390390
/* wraps into a buffered file */
391391
{
392392
PyObject *Buffered_class;
@@ -562,53 +562,73 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
562562
return result;
563563
}
564564

565-
_PyIO_State *
566-
_PyIO_get_module_state(void)
567-
{
568-
PyObject *mod = PyState_FindModule(&_PyIO_Module);
569-
_PyIO_State *state;
570-
if (mod == NULL || (state = get_io_state(mod)) == NULL) {
571-
PyErr_SetString(PyExc_RuntimeError,
572-
"could not find io module state "
573-
"(interpreter shutdown?)");
574-
return NULL;
575-
}
576-
return state;
577-
}
578-
579565
static int
580-
iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
566+
iomodule_traverse(PyObject *mod, visitproc visit, void *arg)
567+
{
581568
_PyIO_State *state = get_io_state(mod);
582-
if (!state->initialized)
583-
return 0;
584569
Py_VISIT(state->locale_module);
585570
Py_VISIT(state->unsupported_operation);
571+
572+
Py_VISIT(state->PyBufferedIOBase_Type);
573+
Py_VISIT(state->PyBufferedRWPair_Type);
574+
Py_VISIT(state->PyBufferedRandom_Type);
575+
Py_VISIT(state->PyBufferedReader_Type);
576+
Py_VISIT(state->PyBufferedWriter_Type);
577+
Py_VISIT(state->PyBytesIOBuffer_Type);
578+
Py_VISIT(state->PyBytesIO_Type);
579+
Py_VISIT(state->PyFileIO_Type);
580+
Py_VISIT(state->PyIOBase_Type);
581+
Py_VISIT(state->PyIncrementalNewlineDecoder_Type);
582+
Py_VISIT(state->PyRawIOBase_Type);
583+
Py_VISIT(state->PyStringIO_Type);
584+
Py_VISIT(state->PyTextIOBase_Type);
585+
Py_VISIT(state->PyTextIOWrapper_Type);
586+
#ifdef MS_WINDOWS
587+
Py_VISIT(state->PyWindowsConsoleIO_Type);
588+
#endif
586589
return 0;
587590
}
588591

589592

590593
static int
591-
iomodule_clear(PyObject *mod) {
594+
iomodule_clear(PyObject *mod)
595+
{
592596
_PyIO_State *state = get_io_state(mod);
593-
if (!state->initialized)
594-
return 0;
595-
if (state->locale_module != NULL)
596-
Py_CLEAR(state->locale_module);
597+
Py_CLEAR(state->locale_module);
597598
Py_CLEAR(state->unsupported_operation);
599+
600+
Py_CLEAR(state->PyBufferedIOBase_Type);
601+
Py_CLEAR(state->PyBufferedRWPair_Type);
602+
Py_CLEAR(state->PyBufferedRandom_Type);
603+
Py_CLEAR(state->PyBufferedReader_Type);
604+
Py_CLEAR(state->PyBufferedWriter_Type);
605+
Py_CLEAR(state->PyBytesIOBuffer_Type);
606+
Py_CLEAR(state->PyBytesIO_Type);
607+
Py_CLEAR(state->PyFileIO_Type);
608+
Py_CLEAR(state->PyIOBase_Type);
609+
Py_CLEAR(state->PyIncrementalNewlineDecoder_Type);
610+
Py_CLEAR(state->PyRawIOBase_Type);
611+
Py_CLEAR(state->PyStringIO_Type);
612+
Py_CLEAR(state->PyTextIOBase_Type);
613+
Py_CLEAR(state->PyTextIOWrapper_Type);
614+
#ifdef MS_WINDOWS
615+
Py_CLEAR(state->PyWindowsConsoleIO_Type);
616+
#endif
598617
return 0;
599618
}
600619

601620
static void
602-
iomodule_free(PyObject *mod) {
603-
iomodule_clear(mod);
621+
iomodule_free(void *mod)
622+
{
623+
(void)iomodule_clear(mod);
604624
}
605625

606626

607627
/*
608628
* Module definition
609629
*/
610630

611-
#define clinic_state() (IO_STATE())
631+
#define clinic_state() (get_io_state(module))
612632
#include "clinic/_iomodule.c.h"
613633
#undef clinic_state
614634

@@ -619,59 +639,48 @@ static PyMethodDef module_methods[] = {
619639
{NULL, NULL}
620640
};
621641

622-
struct PyModuleDef _PyIO_Module = {
623-
.m_base = PyModuleDef_HEAD_INIT,
624-
.m_name = "io",
625-
.m_doc = module_doc,
626-
.m_size = sizeof(_PyIO_State),
627-
.m_methods = module_methods,
628-
.m_traverse = iomodule_traverse,
629-
.m_clear = iomodule_clear,
630-
.m_free = iomodule_free,
631-
};
632-
633-
#define ADD_TYPE(module, type, spec, base) \
634-
do { \
635-
type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
636-
(PyObject *)base); \
637-
if (type == NULL) { \
638-
goto fail; \
639-
} \
640-
if (PyModule_AddType(module, type) < 0) { \
641-
goto fail; \
642-
} \
643-
} while (0)
644-
645-
PyMODINIT_FUNC
646-
PyInit__io(void)
642+
static int
643+
iomodule_exec(PyObject *m)
647644
{
648-
PyObject *m = PyModule_Create(&_PyIO_Module);
649-
_PyIO_State *state = NULL;
650-
if (m == NULL)
651-
return NULL;
652-
state = get_io_state(m);
653-
state->initialized = 0;
645+
_PyIO_State *state = get_io_state(m);
654646

655647
/* DEFAULT_BUFFER_SIZE */
656-
if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
657-
goto fail;
648+
if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) {
649+
return -1;
650+
}
658651

659652
/* UnsupportedOperation inherits from ValueError and OSError */
660653
state->unsupported_operation = PyObject_CallFunction(
661654
(PyObject *)&PyType_Type, "s(OO){}",
662655
"UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
663-
if (state->unsupported_operation == NULL)
664-
goto fail;
656+
if (state->unsupported_operation == NULL) {
657+
return -1;
658+
}
665659
if (PyModule_AddObject(m, "UnsupportedOperation",
666660
Py_NewRef(state->unsupported_operation)) < 0)
667-
goto fail;
661+
{
662+
return -1;
663+
}
668664

669665
/* BlockingIOError, for compatibility */
670666
if (PyModule_AddObjectRef(m, "BlockingIOError",
671-
(PyObject *) PyExc_BlockingIOError) < 0) {
672-
goto fail;
667+
(PyObject *) PyExc_BlockingIOError) < 0)
668+
{
669+
return -1;
673670
}
674671

672+
#define ADD_TYPE(module, type, spec, base) \
673+
do { \
674+
type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
675+
(PyObject *)base); \
676+
if (type == NULL) { \
677+
return -1; \
678+
} \
679+
if (PyModule_AddType(module, type) < 0) { \
680+
return -1; \
681+
} \
682+
} while (0)
683+
675684
// Concrete classes
676685
ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL);
677686

@@ -705,12 +714,30 @@ PyInit__io(void)
705714
ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, base);
706715
ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec, base);
707716

708-
state->initialized = 1;
717+
#undef ADD_TYPE
709718

710-
return m;
719+
return 0;
720+
}
711721

712-
fail:
713-
Py_XDECREF(state->unsupported_operation);
714-
Py_DECREF(m);
715-
return NULL;
722+
static struct PyModuleDef_Slot iomodule_slots[] = {
723+
{Py_mod_exec, iomodule_exec},
724+
{0, NULL},
725+
};
726+
727+
struct PyModuleDef _PyIO_Module = {
728+
.m_base = PyModuleDef_HEAD_INIT,
729+
.m_name = "io",
730+
.m_doc = module_doc,
731+
.m_size = sizeof(_PyIO_State),
732+
.m_methods = module_methods,
733+
.m_traverse = iomodule_traverse,
734+
.m_clear = iomodule_clear,
735+
.m_free = iomodule_free,
736+
.m_slots = iomodule_slots,
737+
};
738+
739+
PyMODINIT_FUNC
740+
PyInit__io(void)
741+
{
742+
return PyModuleDef_Init(&_PyIO_Module);
716743
}

Modules/_io/_iomodule.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err);
137137
extern PyModuleDef _PyIO_Module;
138138

139139
typedef struct {
140-
int initialized;
141140
PyObject *locale_module;
142141

143142
PyObject *unsupported_operation;
@@ -162,9 +161,6 @@ typedef struct {
162161
#endif
163162
} _PyIO_State;
164163

165-
#define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod))
166-
#define IO_STATE() _PyIO_get_module_state()
167-
168164
static inline _PyIO_State *
169165
get_io_state(PyObject *module)
170166
{
@@ -173,7 +169,21 @@ get_io_state(PyObject *module)
173169
return (_PyIO_State *)state;
174170
}
175171

176-
extern _PyIO_State *_PyIO_get_module_state(void);
172+
static inline _PyIO_State *
173+
get_io_state_by_cls(PyTypeObject *cls)
174+
{
175+
void *state = PyType_GetModuleState(cls);
176+
assert(state != NULL);
177+
return (_PyIO_State *)state;
178+
}
179+
180+
static inline _PyIO_State *
181+
find_io_state_by_def(PyTypeObject *type)
182+
{
183+
PyObject *mod = PyType_GetModuleByDef(type, &_PyIO_Module);
184+
assert(mod != NULL);
185+
return get_io_state(mod);
186+
}
177187

178188
#ifdef MS_WINDOWS
179189
extern char _PyIO_get_console_type(PyObject *);

0 commit comments

Comments
 (0)