Skip to content

Commit a4decc0

Browse files
committed
capi per interp (module)
1 parent bfc57d4 commit a4decc0

File tree

4 files changed

+59
-62
lines changed

4 files changed

+59
-62
lines changed

Include/datetime.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ typedef struct {
185185

186186
} PyDateTime_CAPI;
187187

188+
PyAPI_FUNC(PyDateTime_CAPI *) get_datetime_capi(void);
189+
188190
#define PyDateTime_CAPSULE_NAME "datetime.datetime_CAPI"
189191

190192

@@ -194,10 +196,13 @@ typedef struct {
194196
* */
195197
#ifndef _PY_DATETIME_IMPL
196198
/* Define global variable for the C API and a macro for setting it. */
197-
static PyDateTime_CAPI *PyDateTimeAPI = NULL;
199+
#define PyDateTimeAPI get_datetime_capi()
198200

199-
#define PyDateTime_IMPORT \
200-
PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0)
201+
static inline void pydatetime_import(void) {
202+
PyDateTime_CAPI *capi = PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0);
203+
assert(capi == get_datetime_capi());
204+
}
205+
#define PyDateTime_IMPORT pydatetime_import()
201206

202207
/* Macro for access to the UTC singleton */
203208
#define PyDateTime_TimeZone_UTC PyDateTimeAPI->TimeZone_UTC

Include/internal/pycore_interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ struct _is {
217217
// more comments.
218218
struct _obmalloc_state *obmalloc;
219219

220+
void *datetime_module_state;
220221
PyObject *audit_hooks;
221222
PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS];
222223
PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS];

Modules/_datetimemodule.c

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#endif
1313

1414
#include "Python.h"
15+
#include "pycore_interp.h"
1516
#include "pycore_long.h" // _PyLong_GetOne()
1617
#include "pycore_object.h" // _PyObject_Init()
1718
#include "pycore_time.h" // _PyTime_ObjectToTime_t()
@@ -43,6 +44,8 @@
4344
#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType)
4445

4546
typedef struct {
47+
PyDateTime_CAPI capi;
48+
4649
/* Conversion factors. */
4750
PyObject *us_per_ms; // 1_000
4851
PyObject *us_per_second; // 1_000_000
@@ -61,7 +64,29 @@ typedef struct {
6164

6265
static datetime_state _datetime_global_state;
6366

64-
#define STATIC_STATE() (&_datetime_global_state)
67+
static inline datetime_state *
68+
get_module_state(PyObject *module)
69+
{
70+
return &_datetime_global_state;
71+
}
72+
73+
static inline datetime_state *
74+
get_module_state_by_interp(void)
75+
{
76+
PyInterpreterState *interp = _PyInterpreterState_GET();
77+
void *state = interp->datetime_module_state;
78+
assert(state != NULL);
79+
return (datetime_state *)state;
80+
}
81+
82+
PyDateTime_CAPI *
83+
get_datetime_capi(void)
84+
{
85+
return &get_module_state_by_interp()->capi;
86+
}
87+
88+
#define STATIC_STATE() get_module_state_by_interp()
89+
6590

6691
/* We require that C int be at least 32 bits, and use int virtually
6792
* everywhere. In just a few cases we use a temp long, where a Python
@@ -6701,44 +6726,27 @@ static PyMethodDef module_methods[] = {
67016726
{NULL, NULL}
67026727
};
67036728

6704-
/* Get a new C API by calling this function.
6705-
* Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
6706-
*/
6707-
static inline PyDateTime_CAPI *
6708-
get_datetime_capi(void)
6709-
{
6710-
PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI));
6711-
if (capi == NULL) {
6712-
PyErr_NoMemory();
6713-
return NULL;
6714-
}
6715-
capi->DateType = &PyDateTime_DateType;
6716-
capi->DateTimeType = &PyDateTime_DateTimeType;
6717-
capi->TimeType = &PyDateTime_TimeType;
6718-
capi->DeltaType = &PyDateTime_DeltaType;
6719-
capi->TZInfoType = &PyDateTime_TZInfoType;
6720-
capi->Date_FromDate = new_date_ex;
6721-
capi->DateTime_FromDateAndTime = new_datetime_ex;
6722-
capi->Time_FromTime = new_time_ex;
6723-
capi->Delta_FromDelta = new_delta_ex;
6724-
capi->TimeZone_FromTimeZone = new_timezone;
6725-
capi->DateTime_FromTimestamp = datetime_fromtimestamp;
6726-
capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi;
6727-
capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2;
6728-
capi->Time_FromTimeAndFold = new_time_ex2;
6729+
static void
6730+
set_datetime_capi(datetime_state *st)
6731+
{
6732+
st->capi.DateType = &PyDateTime_DateType;
6733+
st->capi.DateTimeType = &PyDateTime_DateTimeType;
6734+
st->capi.TimeType = &PyDateTime_TimeType;
6735+
st->capi.DeltaType = &PyDateTime_DeltaType;
6736+
st->capi.TZInfoType = &PyDateTime_TZInfoType;
6737+
st->capi.Date_FromDate = new_date_ex;
6738+
st->capi.DateTime_FromDateAndTime = new_datetime_ex;
6739+
st->capi.Time_FromTime = new_time_ex;
6740+
st->capi.Delta_FromDelta = new_delta_ex;
6741+
st->capi.TimeZone_FromTimeZone = new_timezone;
6742+
st->capi.DateTime_FromTimestamp = datetime_fromtimestamp;
6743+
st->capi.Date_FromTimestamp = datetime_date_fromtimestamp_capi;
6744+
st->capi.DateTime_FromDateAndTimeAndFold = new_datetime_ex2;
6745+
st->capi.Time_FromTimeAndFold = new_time_ex2;
67296746
// Make sure this function is called after utc has
67306747
// been initialized.
6731-
datetime_state *st = STATIC_STATE();
67326748
assert(st->utc != NULL);
6733-
capi->TimeZone_UTC = st->utc; // borrowed ref
6734-
return capi;
6735-
}
6736-
6737-
static void
6738-
datetime_destructor(PyObject *op)
6739-
{
6740-
void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME);
6741-
PyMem_Free(ptr);
6749+
st->capi.TimeZone_UTC = st->utc; // borrowed ref
67426750
}
67436751

67446752
static int
@@ -6823,6 +6831,10 @@ init_state(datetime_state *st)
68236831
static int
68246832
_datetime_exec(PyObject *module)
68256833
{
6834+
datetime_state *st = get_module_state(module);
6835+
PyInterpreterState *interp = _PyInterpreterState_GET();
6836+
interp->datetime_module_state = st;
6837+
68266838
// `&...` is not a constant expression according to a strict reading
68276839
// of C standards. Fill tp_base at run-time rather than statically.
68286840
// See https://bugs.python.org/issue40777
@@ -6889,7 +6901,6 @@ _datetime_exec(PyObject *module)
68896901
999999, Py_None, 0));
68906902
DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0));
68916903

6892-
datetime_state *st = STATIC_STATE();
68936904
if (init_state(st) < 0) {
68946905
goto error;
68956906
}
@@ -6924,18 +6935,12 @@ _datetime_exec(PyObject *module)
69246935
}
69256936

69266937
/* At last, set up and add the encapsulated C API */
6927-
PyDateTime_CAPI *capi = get_datetime_capi();
6928-
if (capi == NULL) {
6929-
goto error;
6930-
}
6931-
PyObject *capsule = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME,
6932-
datetime_destructor);
6938+
set_datetime_capi(st);
6939+
PyObject *capsule = PyCapsule_New(&st->capi, PyDateTime_CAPSULE_NAME, NULL);
69336940
if (capsule == NULL) {
6934-
PyMem_Free(capi);
69356941
goto error;
69366942
}
69376943
if (PyModule_Add(module, "datetime_CAPI", capsule) < 0) {
6938-
PyMem_Free(capi);
69396944
goto error;
69406945
}
69416946

Modules/_testcapi/datetime.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,9 @@
33
#include "datetime.h" // PyDateTimeAPI
44

55

6-
static int test_run_counter = 0;
7-
86
static PyObject *
97
test_datetime_capi(PyObject *self, PyObject *args)
108
{
11-
if (PyDateTimeAPI) {
12-
if (test_run_counter) {
13-
/* Probably regrtest.py -R */
14-
Py_RETURN_NONE;
15-
}
16-
else {
17-
PyErr_SetString(PyExc_AssertionError,
18-
"PyDateTime_CAPI somehow initialized");
19-
return NULL;
20-
}
21-
}
22-
test_run_counter++;
239
PyDateTime_IMPORT;
2410

2511
if (PyDateTimeAPI) {

0 commit comments

Comments
 (0)