@@ -12,7 +12,7 @@ msgid ""
1212msgstr ""
1313"Project-Id-Version : Python 3.15\n "
1414"Report-Msgid-Bugs-To : \n "
15- "POT-Creation-Date : 2026-06-23 16:23 +0000\n "
15+ "POT-Creation-Date : 2026-07-01 16:21 +0000\n "
1616"PO-Revision-Date : 2026-02-25 14:46+0000\n "
1717"Last-Translator : python-doc bot, 2026\n "
1818"Language-Team : Indonesian (https://app.transifex.com/python-doc/teams/5390/ "
@@ -282,6 +282,80 @@ msgstr ""
282282msgid ":pep:`788`"
283283msgstr ""
284284
285+ msgid "Reusing a thread state across repeated calls"
286+ msgstr ""
287+
288+ msgid ""
289+ "Creating and destroying a :c:type:`PyThreadState` is not free, and is more "
290+ "expensive on a :term:`free-threaded build`. A foreign thread that calls "
291+ "into the interpreter many times -- for example, a worker thread in a native "
292+ "thread pool -- should avoid creating a fresh thread state on every entry and "
293+ "destroying it on every exit. Instead, set up one thread state when the "
294+ "thread starts (or lazily on its first call into Python), attach and detach "
295+ "it around each call, and tear it down once when the thread exits."
296+ msgstr ""
297+
298+ msgid ""
299+ "Manage the thread state explicitly with :c:func:`PyThreadState_New`, "
300+ "attaching and detaching it with :c:func:`PyEval_RestoreThread` and :c:func:"
301+ "`PyEval_SaveThread`. This happens in three distinct phases, at different "
302+ "points in the thread's life."
303+ msgstr ""
304+
305+ msgid ""
306+ "When the thread starts, create one thread state for it. ``interp`` is the "
307+ "target interpreter, captured by the code that created this thread while it "
308+ "held an attached thread state (for example via :c:func:"
309+ "`PyInterpreterState_Get`)::"
310+ msgstr ""
311+
312+ msgid "PyThreadState *tstate = PyThreadState_New(interp);"
313+ msgstr ""
314+
315+ msgid ""
316+ "Then, on each call into Python -- which may happen many times over the "
317+ "thread's life -- attach the thread state, make the Python C API calls that "
318+ "require it, and detach again so the thread does not hold the GIL while off "
319+ "doing non-Python work::"
320+ msgstr ""
321+
322+ msgid ""
323+ "PyEval_RestoreThread(tstate);\n"
324+ "result = CallSomeFunction(); /* your Python C API calls go here */\n"
325+ "PyEval_SaveThread();"
326+ msgstr ""
327+
328+ msgid ""
329+ "When the thread is finished calling into Python, destroy the thread state "
330+ "once::"
331+ msgstr ""
332+
333+ msgid ""
334+ "PyEval_RestoreThread(tstate);\n"
335+ "PyThreadState_Clear(tstate);\n"
336+ "PyThreadState_DeleteCurrent();"
337+ msgstr ""
338+
339+ msgid ""
340+ "The general-purpose entry points for calling in from a foreign thread -- :c:"
341+ "func:`PyThreadState_Ensure` and the older :c:func:`PyGILState_Ensure` -- do "
342+ "*not* guarantee a persistent thread state: their thread-state lifetime is "
343+ "deliberately implementation-defined, so a matched acquire/release pair may "
344+ "create and destroy a thread state each time. Use :c:func:"
345+ "`PyThreadState_New`, as shown here, whenever you specifically want to reuse "
346+ "one thread state across calls."
347+ msgstr ""
348+
349+ msgid ""
350+ "The code that created the foreign thread must arrange for the shutdown "
351+ "sequence to run before the thread exits, and before :c:func:`Py_FinalizeEx` "
352+ "is called. If interpreter finalization begins first, the shutdown :c:func:"
353+ "`PyEval_RestoreThread` call will hang the thread rather than return (see :"
354+ "ref:`cautions-regarding-runtime-finalization`). If the thread exits without "
355+ "running the shutdown sequence, the thread state is leaked for the remainder "
356+ "of the process."
357+ msgstr ""
358+
285359msgid "Attaching/detaching thread states"
286360msgstr ""
287361
0 commit comments