@@ -282,46 +282,19 @@ Attaching/detaching thread states
282282 Otherwise, if both of the above cases fail, a new thread state is created
283283 for *guard*. It is then attached and marked as owned by ``PyThreadState_Ensure``.
284284
285- This function will return ``NULL`` to indicate a memory allocation failure, and
286- otherwise return a pointer to the thread state that was previously attached
287- (which might have been ``NULL ``, in which case an non-``NULL `` sentinel value is
288- returned instead to differentiate between failure -- this means that this function
289- will sometimes return an invalid ``PyThreadState `` pointer).
290-
291- To visualize, this function is roughly equivalent to the following:
292-
293- .. code-block:: c
294-
295- PyThreadState *
296- PyThreadState_Ensure(PyInterpreterGuard *guard)
297- {
298- assert(guard != NULL);
299- PyInterpreterState *interp = PyInterpreterGuard_GetInterpreter(guard);
300- assert(interp != NULL);
301-
302- PyThreadState *current_tstate = PyThreadState_GetUnchecked();
303- if (current_tstate == NULL) {
304- PyThreadState *last_used = PyGILState_GetThisThreadState();
305- if (last_used != NULL) {
306- ++last_used->ensure_counter;
307- PyThreadState_Swap(last_used);
308- return NO_TSTATE_SENTINEL;
309- }
310- } else if (current_tstate->interp == interp) {
311- ++current_tstate->ensure_counter;
312- return current_tstate;
313- }
314-
315- PyThreadState *new_tstate = PyThreadState_New(interp);
316- if (new_tstate == NULL) {
317- return NULL;
318- }
319-
320- ++new_tstate->ensure_counter;
321- new_tstate->owned_by_pythreadstate_ensure = true;
322- PyThreadState_Swap(new_tstate);
323- return current_tstate == NULL ? NO_TSTATE_SENTINEL : current_tstate;
324- }
285+ The function's effect (if any) will be reversed by the matching call to
286+ :c:func:`PyThreadState_Release`.
287+
288+ On error, this function returns ``NULL`` *without* an exception set.
289+ Do not call :c:func:`!PyThreadState_Release` in this case.
290+
291+ On success, this function returns a pointer to the :term:`thread state` that
292+ was previously attached, or, if no state was previously attached, a value that
293+ is not a valid :c:type:`!PyThreadState` pointer.
294+
295+ The returned value must be passed to the matching call to :c:func:`!PyThreadState_Release`,
296+ and must not be passed to any other C API functions
297+ (unless it matches a known valid :c:type: `!PyThreadState ` pointer).
325298
326299 .. versionadded:: next
327300
@@ -330,53 +303,17 @@ Attaching/detaching thread states
330303
331304 Get an attached thread state for the interpreter referenced by *view *.
332305
333- *view * must not be ``NULL ``. If the interpreter referenced by *view * has been
334- finalized or is currently finalizing, then this function returns ``NULL `` without
335- setting an exception. This function may also return ``NULL `` on other errors,
336- such memory allocation failure.
337-
338- The interpreter referenced by *view * will be implicitly guarded. The
339- guard will be released upon the corresponding :c:func: `PyThreadState_Release `
306+ On success, the interpreter referenced by *view * will be implicitly guarded;
307+ the guard will be released upon the corresponding :c:func: `PyThreadState_Release `
340308 call.
341-
342- On success, this function will return the thread state that was previously attached.
343- If no thread state was previously attached, this returns a non-``NULL `` sentinel
344- value. The behavior of whether this function creates a thread state is
345- equivalent to that of :c:func: `PyThreadState_Ensure `.
346-
347- To visualize, function is roughly equivalent to the following:
348-
349- .. code-block :: c
350-
351- PyThreadState *
352- PyThreadState_EnsureFromView(PyInterpreterView *view)
353- {
354- assert(view != NULL);
355- PyInterpreterGuard *guard = PyInterpreterGuard_FromView(view);
356- if (guard == NULL) {
357- return NULL;
358- }
359-
360- PyThreadState *tstate = PyThreadState_Ensure(guard);
361- if (tstate == NULL) {
362- PyInterpreterGuard_Close(guard);
363- return NULL;
364- }
365-
366- if (tstate->guard == NULL) {
367- tstate->guard = guard;
368- } else {
369- PyInterpreterGuard_Close(guard);
370- }
371-
372- return tstate;
373- }
309+ Otherwise, the behavior and return value are the same as for
310+ :c:func: `PyThreadState_Ensure `.
374311
375312
376313.. c :function :: void PyThreadState_Release (PyThreadState *tstate)
377314
378315 Undo a :c:func: `PyThreadState_Ensure ` call. This must be called exactly once
379- for each call to ``PyThreadState_Ensure ``.
316+ for each successful call to ``PyThreadState_Ensure ``.
380317
381318 This function will decrement an internal counter on the attached thread state. If
382319 this counter ever reaches below zero, this function emits a fatal error (via
@@ -390,47 +327,6 @@ Attaching/detaching thread states
390327 If *tstate* indicates that no prior thread state was attached, there will be
391328 no attached thread state upon returning.
392329
393- To visualize, this function is roughly equivalent to the following:
394-
395- .. code-block:: c
396-
397- void
398- PyThreadState_Release(PyThreadState *old_tstate)
399- {
400- PyThreadState *current_tstate = PyThreadState_Get();
401- assert(old_tstate != NULL);
402- assert(current_tstate != NULL);
403- assert(current_tstate->ensure_counter > 0);
404- if (--current_tstate->ensure_counter > 0) {
405- // There are remaining PyThreadState_Ensure() calls
406- // for this thread state.
407- return;
408- }
409-
410- assert(current_tstate->ensure_counter == 0);
411- if (old_tstate == NO_TSTATE_SENTINEL) {
412- // No thread state was attached prior the PyThreadState_Ensure ()
413- // call. So, we can just destroy the current thread state and return.
414- assert(current_tstate->owned_by_pythreadstate_ensure );
415- PyThreadState_Clear (current_tstate);
416- PyThreadState_DeleteCurrent ();
417- return;
418- }
419-
420- if (tstate->guard != NULL ) {
421- PyInterpreterGuard_Close (tstate->guard );
422- return;
423- }
424-
425- if (tstate->owned_by_pythreadstate_ensure) {
426- // The attached thread state was created by the initial PyThreadState_Ensure ()
427- // call. It's our job to destroy it.
428- PyThreadState_Clear (current_tstate);
429- PyThreadState_DeleteCurrent ();
430- }
431-
432- PyThreadState_Swap (old_tstate);
433- }
434330
435331.. _legacy-api:
436332.. _gilstate:
0 commit comments