RecompExternalPython for N64Recompiled 2.0.0
Loading...
Searching...
No Matches
(Sub)Interpreter Functions

Functions Used for REPY's Interpreter Stack, which handles interpreter/subinterpreter operations as well as PyThreadState management. More...

Functions

void REPY_PushInterpreter (REPY_InterpreterIndex interpreter_handle)
 Pushes an interpreter index to the interpreter stack, and switching the active interpreter if necessary.
void REPY_PopInterpreter ()
 Pops an interpreter index from the interpreter stack, switching active interpreters if necessary.
REPY_InterpreterIndex REPY_GetCurrentInterpreter ()
 Gets the interpreter index at the top of the interpreter stack.
REPY_bool REPY_GetInterpreterAutoDisarm (REPY_InterpreterIndex index)
 Gets whether or not this subinterpreter should be 'disarmed' when shutting down.
void REPY_SetInterpreterAutoDisarm (REPY_InterpreterIndex index, REPY_bool value)
 Sets whether or not this subinterpreter should be 'disarmed' when shutting down.
REPY_InterpreterIndex REPY_GetHandleInterpreter (REPY_Handle handle_no_release)
 Gets the index of the interpreter a specific REPY_Handle object is associated with.

Detailed Description

Functions Used for REPY's Interpreter Stack, which handles interpreter/subinterpreter operations as well as PyThreadState management.

REPY used a free-threaded build of Python, with the traditional Python GIL is a non-factor. However, the CPython still needs to know whether or not a given thread needs access to the interpreter (and when subinterpreters are in use, which interpreter) using an opaque struct in CPython called PyThreadState.

Because the mod developer has no control over what other mods a player may install, and whether these mods use REPY, no single mod can be given responsibility for managing the PyThreadState directly. Therefore, REPY implements something called the Interpreter Stack: If a given mod code thread requires access to the main interpreter, a call to REPY_PushInterpreter tells REPY a mod needs access to a specific interpreter, and a call to REPY_PopInterpreter tells REPY that the previously requested access is no longer needed. Using this, REPY itself manages the PyThreadState of a given N64Recompiled thread, making changes to the state only necessary.

For this reason, it is recommended to call REPY_PushInterpreter at the top of any function that needs Python interpreter access, and to call REPY_PopInterpreter before that function returns. The exception is when REPY_FN macros, as the setup and cleanup macros will automatically do this for you.

waitr* See Interpreter Stack Management for potential performance pitfalls related to Interpreter Stack management.

See Subinterpreters for more information on what they are, and REPY's usage of them.

Function Documentation

◆ REPY_GetCurrentInterpreter()

REPY_InterpreterIndex REPY_GetCurrentInterpreter ( )

Gets the interpreter index at the top of the interpreter stack.

Returns REPY_INTERPRETER_STACK_EMPTY when the interpreter stack is empty. See Subinterpreters for more information.

Returns
the interpreter index at the top of the stack.

◆ REPY_GetHandleInterpreter()

REPY_InterpreterIndex REPY_GetHandleInterpreter ( REPY_Handle handle_no_release)

Gets the index of the interpreter a specific REPY_Handle object is associated with.

This function will not release Single-Use handles.

Parameters
handle_no_releasea REPY_Handle for get the interpreter for.
Returns
the interpreter index corresponding to this REPY_Handle.

◆ REPY_GetInterpreterAutoDisarm()

REPY_bool REPY_GetInterpreterAutoDisarm ( REPY_InterpreterIndex index)

Gets whether or not this subinterpreter should be 'disarmed' when shutting down.

This is a workaround for N64Recompiled titles freezing on exit when a subinterpreter has additional threads running. When auto-disarm is set to true, REPY will simply let the subinterpreter leak and be cleaned up by the OS. It's hardly a clean exit, but it's the best solution we have until a proper on_shutdown event is implemented in the N64Recompiled runtime.

Parameters
indexThe subinterpreter to set this value for. Does nothing for the main interpreter.

◆ REPY_PopInterpreter()

void REPY_PopInterpreter ( )

Pops an interpreter index from the interpreter stack, switching active interpreters if necessary.

See Subinterpreters for more information.

◆ REPY_PushInterpreter()

void REPY_PushInterpreter ( REPY_InterpreterIndex interpreter_handle)

Pushes an interpreter index to the interpreter stack, and switching the active interpreter if necessary.

See Subinterpreters for more information.

Parameters
interpreter_handleThe index to push to the subinterpreter stack.

◆ REPY_SetInterpreterAutoDisarm()

void REPY_SetInterpreterAutoDisarm ( REPY_InterpreterIndex index,
REPY_bool value )

Sets whether or not this subinterpreter should be 'disarmed' when shutting down.

This is a workaround for N64Recompiled titles freezing on exit when a subinterpreter has additional threads running. When auto-disarm is set to true, REPY will simply let the subinterpreter leak and be cleaned up by the OS. It's hardly a clean exit, but it's the best solution we have until a proper on_shutdown event is implemented in the N64Recompiled runtime.

Parameters
indexThe subinterpreter to set this value for. Does nothing for the main interpreter.
valueThe new value for auto-disarm.