mirror of https://github.com/python/cpython
gh-94673: Clarify About Runtime State Related to Static Builtin Types (gh-117761)
Guido pointed out to me that some details about the per-interpreter state for the builtin types aren't especially clear. I'm addressing that by: * adding a comment explaining that state * adding some asserts to point out the relationship between each index and the interp/global runtime state
This commit is contained in:
parent
30f0643e36
commit
eca53620e3
|
@ -68,6 +68,43 @@ struct types_state {
|
||||||
unsigned int next_version_tag;
|
unsigned int next_version_tag;
|
||||||
|
|
||||||
struct type_cache type_cache;
|
struct type_cache type_cache;
|
||||||
|
|
||||||
|
/* Every static builtin type is initialized for each interpreter
|
||||||
|
during its own initialization, including for the main interpreter
|
||||||
|
during global runtime initialization. This is done by calling
|
||||||
|
_PyStaticType_InitBuiltin().
|
||||||
|
|
||||||
|
The first time a static builtin type is initialized, all the
|
||||||
|
normal PyType_Ready() stuff happens. The only difference from
|
||||||
|
normal is that there are three PyTypeObject fields holding
|
||||||
|
objects which are stored here (on PyInterpreterState) rather
|
||||||
|
than in the corresponding PyTypeObject fields. Those are:
|
||||||
|
tp_dict (cls.__dict__), tp_subclasses (cls.__subclasses__),
|
||||||
|
and tp_weaklist.
|
||||||
|
|
||||||
|
When a subinterpreter is initialized, each static builtin type
|
||||||
|
is still initialized, but only the interpreter-specific portion,
|
||||||
|
namely those three objects.
|
||||||
|
|
||||||
|
Those objects are stored in the PyInterpreterState.types.builtins
|
||||||
|
array, at the index corresponding to each specific static builtin
|
||||||
|
type. That index (a size_t value) is stored in the tp_subclasses
|
||||||
|
field. For static builtin types, we re-purposed the now-unused
|
||||||
|
tp_subclasses to avoid adding another field to PyTypeObject.
|
||||||
|
In all other cases tp_subclasses holds a dict like before.
|
||||||
|
(The field was previously defined as PyObject*, but is now void*
|
||||||
|
to reflect its dual use.)
|
||||||
|
|
||||||
|
The index for each static builtin type isn't statically assigned.
|
||||||
|
Instead it is calculated the first time a type is initialized
|
||||||
|
(by the main interpreter). The index matches the order in which
|
||||||
|
the type was initialized relative to the others. The actual
|
||||||
|
value comes from the current value of num_builtins_initialized,
|
||||||
|
as each type is initialized for the main interpreter.
|
||||||
|
|
||||||
|
num_builtins_initialized is incremented once for each static
|
||||||
|
builtin type. Once initialization is over for a subinterpreter,
|
||||||
|
the value will be the same as for all other interpreters. */
|
||||||
size_t num_builtins_initialized;
|
size_t num_builtins_initialized;
|
||||||
static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
|
static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
|
||||||
PyMutex mutex;
|
PyMutex mutex;
|
||||||
|
|
|
@ -162,9 +162,14 @@ _PyStaticType_GetState(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
static void
|
static void
|
||||||
static_builtin_state_init(PyInterpreterState *interp, PyTypeObject *self)
|
static_builtin_state_init(PyInterpreterState *interp, PyTypeObject *self)
|
||||||
{
|
{
|
||||||
if (!static_builtin_index_is_set(self)) {
|
if (_Py_IsMainInterpreter(interp)) {
|
||||||
|
assert(!static_builtin_index_is_set(self));
|
||||||
static_builtin_index_set(self, interp->types.num_builtins_initialized);
|
static_builtin_index_set(self, interp->types.num_builtins_initialized);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
assert(static_builtin_index_get(self) ==
|
||||||
|
interp->types.num_builtins_initialized);
|
||||||
|
}
|
||||||
static_builtin_state *state = static_builtin_state_get(interp, self);
|
static_builtin_state *state = static_builtin_state_get(interp, self);
|
||||||
|
|
||||||
/* It should only be called once for each builtin type. */
|
/* It should only be called once for each builtin type. */
|
||||||
|
|
Loading…
Reference in New Issue