Skip to content

Commit 5955de6

Browse files
committed
Add strong interpreter reference functions.
1 parent 54b0ce0 commit 5955de6

2 files changed

Lines changed: 52 additions & 20 deletions

File tree

Include/cpython/pystate.h

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -277,23 +277,36 @@ PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameFunc(
277277
PyInterpreterState *interp,
278278
_PyFrameEvalFunction eval_frame);
279279

280-
/* Similar to PyInterpreterState_Get(), but returns the interpreter with an
281-
* incremented reference count. PyInterpreterState_Delete() won't delete the
282-
* full interpreter structure until the reference is released by
283-
* PyThreadState_Ensure() or PyInterpreterState_Release(). */
284-
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Hold(void);
280+
/* Strong interpreter references */
285281

286-
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Lookup(int64_t interp_id);
282+
typedef uintptr_t PyInterpreterRef;
287283

288-
/* Release a reference to an interpreter incremented by PyInterpreterState_Hold() */
289-
PyAPI_FUNC(void) PyInterpreterState_Release(PyInterpreterState *interp);
284+
PyAPI_FUNC(PyInterpreterRef) PyInterpreterRef_Get(void);
285+
PyAPI_FUNC(PyInterpreterRef) PyInterpreterRef_Dup(PyInterpreterRef ref);
286+
PyAPI_FUNC(PyInterpreterRef) PyInterpreterState_AsStrong(PyInterpreterState *interp);
287+
PyAPI_FUNC(void) PyInterpreterRef_Close(PyInterpreterRef ref);
288+
289+
#define PyInterpreterRef_Close(ref) do { \
290+
PyInterpreterRef_Close(ref); \
291+
ref = 0; \
292+
} while (0); \
293+
294+
/* Weak interpreter references */
295+
296+
typedef struct _interpreter_weakref {
297+
int64_t id;
298+
Py_ssize_t refcount;
299+
} PyInterpreterWeakRef;
300+
301+
PyAPI_FUNC(PyInterpreterWeakRef) PyInterpreterWeakRef_Get(void);
302+
PyAPI_FUNC(PyInterpreterWeakRef) PyInterpreterWeakRef_Dup(PyInterpreterWeakRef wref);
303+
PyAPI_FUNC(PyInterpreterRef) PyInterpreterWeakRef_AsStrong(PyInterpreterWeakRef wref);
304+
PyAPI_FUNC(void) PyInterpreterWeakRef_Close(PyInterpreterWeakRef wref);
290305

291306
// Exports for '_testcapi' shared extension
292307
PyAPI_FUNC(Py_ssize_t) _PyInterpreterState_Refcount(PyInterpreterState *interp);
293308
PyAPI_FUNC(void) _PyInterpreterState_Incref(PyInterpreterState *interp);
294309

295-
PyAPI_FUNC(int) PyThreadState_SetDaemon(int daemon);
296-
297310
PyAPI_FUNC(int) PyThreadState_Ensure(PyInterpreterState *interp);
298311

299312
PyAPI_FUNC(void) PyThreadState_Release(void);

Python/pystate.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3229,12 +3229,38 @@ _PyInterpreterState_Incref(PyInterpreterState *interp)
32293229
_Py_atomic_add_ssize(&interp->threads.finalizing.countdown, 1);
32303230
}
32313231

3232-
PyInterpreterState *
3233-
PyInterpreterState_Hold(void)
3232+
static PyInterpreterState *
3233+
ref_as_interp(PyInterpreterRef ref)
3234+
{
3235+
PyInterpreterState *interp = (PyInterpreterState *)ref;
3236+
if (interp == NULL) {
3237+
Py_FatalError("Got a null interpreter reference, likely due to use after close.");
3238+
}
3239+
3240+
return interp;
3241+
}
3242+
3243+
PyInterpreterRef
3244+
PyInterpreterRef_Get(void)
32343245
{
32353246
PyInterpreterState *interp = PyInterpreterState_Get();
32363247
_PyInterpreterState_Incref(interp);
3237-
return interp;
3248+
return (PyInterpreterRef)interp;
3249+
}
3250+
3251+
PyInterpreterRef
3252+
PyInterpreterRef_Dup(PyInterpreterRef ref)
3253+
{
3254+
PyInterpreterState *interp = ref_as_interp(ref);
3255+
_PyInterpreterState_Incref(interp);
3256+
return (PyInterpreterRef)interp;
3257+
}
3258+
3259+
void
3260+
PyInterpreterRef_Close(PyInterpreterRef ref)
3261+
{
3262+
PyInterpreterState *interp = ref_as_interp(ref);
3263+
decref_interpreter(ref);
32383264
}
32393265

32403266
PyInterpreterState *
@@ -3260,13 +3286,6 @@ PyInterpreterState_Lookup(int64_t interp_id)
32603286
return interp;
32613287
}
32623288

3263-
void
3264-
PyInterpreterState_Release(PyInterpreterState *interp)
3265-
{
3266-
assert(interp != NULL);
3267-
decref_interpreter(interp);
3268-
}
3269-
32703289
int
32713290
PyThreadState_Ensure(PyInterpreterState *interp)
32723291
{

0 commit comments

Comments
 (0)