Skip to content

Commit

Permalink
gh-117398: Use Per-Interpreter State for the _datetime Static Types (g…
Browse files Browse the repository at this point in the history
…h-119929)

We make use of the same mechanism that we use for the static builtin types.  This required a few tweaks.

The relevant code could use some cleanup but I opted to avoid the significant churn in this change.  I'll tackle that separately.

This change is the final piece needed to make _datetime support multiple interpreters.  I've updated the module slot accordingly.
  • Loading branch information
ericsnowcurrently authored Jun 3, 2024
1 parent dba7a16 commit 105f22e
Show file tree
Hide file tree
Showing 13 changed files with 381 additions and 166 deletions.
2 changes: 1 addition & 1 deletion Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
if (PyType_Check(op) &&
((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
PyInterpreterState *interp = _PyInterpreterState_GET();
static_builtin_state *state = _PyStaticType_GetState(
managed_static_type_state *state = _PyStaticType_GetState(
interp, (PyTypeObject *)op);
return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
}
Expand Down
48 changes: 38 additions & 10 deletions Include/internal/pycore_typeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ struct type_cache {

/* For now we hard-code this to a value for which we are confident
all the static builtin types will fit (for all builds). */
#define _Py_MAX_STATIC_BUILTIN_TYPES 200
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10

typedef struct {
PyTypeObject *type;
int isbuiltin;
int readying;
int ready;
// XXX tp_dict can probably be statically allocated,
Expand All @@ -59,7 +61,7 @@ typedef struct {
are also some diagnostic uses for the list of weakrefs,
so we still keep it. */
PyObject *tp_weaklist;
} static_builtin_state;
} managed_static_type_state;

struct types_state {
/* Used to set PyTypeObject.tp_version_tag.
Expand Down Expand Up @@ -105,8 +107,16 @@ struct types_state {
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;
static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
struct {
size_t num_initialized;
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES];
} builtins;
/* We apply a similar strategy for managed extension modules. */
struct {
size_t num_initialized;
size_t next_index;
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_EXT_TYPES];
} for_extensions;
PyMutex mutex;
};

Expand All @@ -130,12 +140,35 @@ typedef struct wrapperbase pytype_slotdef;


static inline PyObject **
_PyStaticType_GET_WEAKREFS_LISTPTR(static_builtin_state *state)
_PyStaticType_GET_WEAKREFS_LISTPTR(managed_static_type_state *state)
{
assert(state != NULL);
return &state->tp_weaklist;
}

extern int _PyStaticType_InitBuiltin(
PyInterpreterState *interp,
PyTypeObject *type);
extern void _PyStaticType_FiniBuiltin(
PyInterpreterState *interp,
PyTypeObject *type);
extern void _PyStaticType_ClearWeakRefs(
PyInterpreterState *interp,
PyTypeObject *type);
extern managed_static_type_state * _PyStaticType_GetState(
PyInterpreterState *interp,
PyTypeObject *type);

// Export for '_datetime' shared extension.
PyAPI_FUNC(int) _PyStaticType_InitForExtension(
PyInterpreterState *interp,
PyTypeObject *self);
PyAPI_FUNC(void) _PyStaticType_FiniForExtension(
PyInterpreterState *interp,
PyTypeObject *self,
int final);


/* Like PyType_GetModuleState, but skips verification
* that type is a heap type with an associated module */
static inline void *
Expand All @@ -151,11 +184,6 @@ _PyType_GetModuleState(PyTypeObject *type)
}


extern int _PyStaticType_InitBuiltin(PyInterpreterState *, PyTypeObject *type);
extern static_builtin_state * _PyStaticType_GetState(PyInterpreterState *, PyTypeObject *);
extern void _PyStaticType_ClearWeakRefs(PyInterpreterState *, PyTypeObject *type);
extern void _PyStaticType_Dealloc(PyInterpreterState *, PyTypeObject *);

// Export for 'math' shared extension, used via _PyType_IsReady() static inline
// function
PyAPI_FUNC(PyObject *) _PyType_GetDict(PyTypeObject *);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The ``_datetime`` module (C implementation for :mod:`datetime`) now supports
being imported in multiple interpreters.
Loading

0 comments on commit 105f22e

Please sign in to comment.