summaryrefslogtreecommitdiffstats
path: root/Include/internal/pycore_crossinterp.h
diff options
context:
space:
mode:
Diffstat (limited to 'Include/internal/pycore_crossinterp.h')
-rw-r--r--Include/internal/pycore_crossinterp.h128
1 files changed, 128 insertions, 0 deletions
diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h
index 59e4cd9..9600dfb 100644
--- a/Include/internal/pycore_crossinterp.h
+++ b/Include/internal/pycore_crossinterp.h
@@ -8,6 +8,8 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_pyerrors.h"
+
/***************************/
/* cross-interpreter calls */
@@ -124,6 +126,8 @@ struct _xidregitem {
};
struct _xidregistry {
+ int global; /* builtin types or heap types */
+ int initialized;
PyThread_type_lock mutex;
struct _xidregitem *head;
};
@@ -133,6 +137,130 @@ PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *);
PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *);
+/*****************************/
+/* runtime state & lifecycle */
+/*****************************/
+
+struct _xi_runtime_state {
+ // builtin types
+ // XXX Remove this field once we have a tp_* slot.
+ struct _xidregistry registry;
+};
+
+struct _xi_state {
+ // heap types
+ // XXX Remove this field once we have a tp_* slot.
+ struct _xidregistry registry;
+
+ // heap types
+ PyObject *PyExc_NotShareableError;
+};
+
+extern PyStatus _PyXI_Init(PyInterpreterState *interp);
+extern void _PyXI_Fini(PyInterpreterState *interp);
+
+
+/***************************/
+/* short-term data sharing */
+/***************************/
+
+typedef enum error_code {
+ _PyXI_ERR_NO_ERROR = 0,
+ _PyXI_ERR_UNCAUGHT_EXCEPTION = -1,
+ _PyXI_ERR_OTHER = -2,
+ _PyXI_ERR_NO_MEMORY = -3,
+ _PyXI_ERR_ALREADY_RUNNING = -4,
+ _PyXI_ERR_MAIN_NS_FAILURE = -5,
+ _PyXI_ERR_APPLY_NS_FAILURE = -6,
+ _PyXI_ERR_NOT_SHAREABLE = -7,
+} _PyXI_errcode;
+
+
+typedef struct _sharedexception {
+ // The originating interpreter.
+ PyInterpreterState *interp;
+ // The kind of error to propagate.
+ _PyXI_errcode code;
+ // The exception information to propagate, if applicable.
+ // This is populated only for _PyXI_ERR_UNCAUGHT_EXCEPTION.
+ _Py_excinfo uncaught;
+} _PyXI_exception_info;
+
+PyAPI_FUNC(void) _PyXI_ApplyExceptionInfo(
+ _PyXI_exception_info *info,
+ PyObject *exctype);
+
+typedef struct xi_session _PyXI_session;
+typedef struct _sharedns _PyXI_namespace;
+
+PyAPI_FUNC(void) _PyXI_FreeNamespace(_PyXI_namespace *ns);
+PyAPI_FUNC(_PyXI_namespace *) _PyXI_NamespaceFromNames(PyObject *names);
+PyAPI_FUNC(int) _PyXI_FillNamespaceFromDict(
+ _PyXI_namespace *ns,
+ PyObject *nsobj,
+ _PyXI_session *session);
+PyAPI_FUNC(int) _PyXI_ApplyNamespace(
+ _PyXI_namespace *ns,
+ PyObject *nsobj,
+ PyObject *dflt);
+
+
+// A cross-interpreter session involves entering an interpreter
+// (_PyXI_Enter()), doing some work with it, and finally exiting
+// that interpreter (_PyXI_Exit()).
+//
+// At the boundaries of the session, both entering and exiting,
+// data may be exchanged between the previous interpreter and the
+// target one in a thread-safe way that does not violate the
+// isolation between interpreters. This includes setting objects
+// in the target's __main__ module on the way in, and capturing
+// uncaught exceptions on the way out.
+struct xi_session {
+ // Once a session has been entered, this is the tstate that was
+ // current before the session. If it is different from cur_tstate
+ // then we must have switched interpreters. Either way, this will
+ // be the current tstate once we exit the session.
+ PyThreadState *prev_tstate;
+ // Once a session has been entered, this is the current tstate.
+ // It must be current when the session exits.
+ PyThreadState *init_tstate;
+ // This is true if init_tstate needs cleanup during exit.
+ int own_init_tstate;
+
+ // This is true if, while entering the session, init_thread took
+ // "ownership" of the interpreter's __main__ module. This means
+ // it is the only thread that is allowed to run code there.
+ // (Caveat: for now, users may still run exec() against the
+ // __main__ module's dict, though that isn't advisable.)
+ int running;
+ // This is a cached reference to the __dict__ of the entered
+ // interpreter's __main__ module. It is looked up when at the
+ // beginning of the session as a convenience.
+ PyObject *main_ns;
+
+ // This is set if the interpreter is entered and raised an exception
+ // that needs to be handled in some special way during exit.
+ _PyXI_errcode *exc_override;
+ // This is set if exit captured an exception to propagate.
+ _PyXI_exception_info *exc;
+
+ // -- pre-allocated memory --
+ _PyXI_exception_info _exc;
+ _PyXI_errcode _exc_override;
+};
+
+PyAPI_FUNC(int) _PyXI_Enter(
+ _PyXI_session *session,
+ PyInterpreterState *interp,
+ PyObject *nsupdates);
+PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session);
+
+PyAPI_FUNC(void) _PyXI_ApplyCapturedException(
+ _PyXI_session *session,
+ PyObject *excwrapper);
+PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session);
+
+
#ifdef __cplusplus
}
#endif