| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | /* InterpreterID object */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2024-03-21 09:56:12 -06:00
										 |  |  | #include "pycore_interp.h"        // _PyInterpreterState_LookUpID()
 | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  | #include "interpreteridobject.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct interpid { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     int64_t id; | 
					
						
							|  |  |  | } interpid; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-21 09:56:12 -06:00
										 |  |  | int64_t | 
					
						
							|  |  |  | _PyInterpreterID_GetID(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!PyObject_TypeCheck(self, &PyInterpreterID_Type)) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                      "expected an InterpreterID, got %R", | 
					
						
							|  |  |  |                      self); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int64_t id = ((interpid *)self)->id; | 
					
						
							|  |  |  |     assert(id >= 0); | 
					
						
							|  |  |  |     return id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | static interpid * | 
					
						
							|  |  |  | newinterpid(PyTypeObject *cls, int64_t id, int force) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyInterpreterState *interp = _PyInterpreterState_LookUpID(id); | 
					
						
							|  |  |  |     if (interp == NULL) { | 
					
						
							|  |  |  |         if (force) { | 
					
						
							|  |  |  |             PyErr_Clear(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-28 13:40:44 +02:00
										 |  |  |     if (interp != NULL) { | 
					
						
							|  |  |  |         if (_PyInterpreterState_IDIncref(interp) < 0) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     interpid *self = PyObject_New(interpid, cls); | 
					
						
							|  |  |  |     if (self == NULL) { | 
					
						
							| 
									
										
										
										
											2021-04-28 13:40:44 +02:00
										 |  |  |         if (interp != NULL) { | 
					
						
							|  |  |  |             _PyInterpreterState_IDDecref(interp); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->id = id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-25 18:35:57 +03:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static char *kwlist[] = {"id", "force", NULL}; | 
					
						
							| 
									
										
										
										
											2024-03-21 09:56:12 -06:00
										 |  |  |     PyObject *idobj; | 
					
						
							| 
									
										
										
										
											2019-09-25 18:35:57 +03:00
										 |  |  |     int force = 0; | 
					
						
							|  |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | 
					
						
							| 
									
										
										
										
											2024-03-21 09:56:12 -06:00
										 |  |  |                                      "O|$p:InterpreterID.__init__", kwlist, | 
					
						
							|  |  |  |                                      &idobj, &force)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int64_t id = _PyInterpreterState_ObjectToID(idobj); | 
					
						
							|  |  |  |     if (id < 0) { | 
					
						
							| 
									
										
										
										
											2019-09-25 18:35:57 +03:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (PyObject *)newinterpid(cls, id, force); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | interpid_dealloc(PyObject *v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int64_t id = ((interpid *)v)->id; | 
					
						
							|  |  |  |     PyInterpreterState *interp = _PyInterpreterState_LookUpID(id); | 
					
						
							|  |  |  |     if (interp != NULL) { | 
					
						
							|  |  |  |         _PyInterpreterState_IDDecref(interp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         // already deleted
 | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_TYPE(v)->tp_free(v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interpid_repr(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyTypeObject *type = Py_TYPE(self); | 
					
						
							|  |  |  |     const char *name = _PyType_Name(type); | 
					
						
							|  |  |  |     interpid *id = (interpid *)self; | 
					
						
							|  |  |  |     return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interpid_str(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpid *id = (interpid *)self; | 
					
						
							|  |  |  |     return PyUnicode_FromFormat("%" PRId64 "", id->id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interpid_int(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpid *id = (interpid *)self; | 
					
						
							|  |  |  |     return PyLong_FromLongLong(id->id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyNumberMethods interpid_as_number = { | 
					
						
							|  |  |  |      0,                       /* nb_add */ | 
					
						
							|  |  |  |      0,                       /* nb_subtract */ | 
					
						
							|  |  |  |      0,                       /* nb_multiply */ | 
					
						
							|  |  |  |      0,                       /* nb_remainder */ | 
					
						
							|  |  |  |      0,                       /* nb_divmod */ | 
					
						
							|  |  |  |      0,                       /* nb_power */ | 
					
						
							|  |  |  |      0,                       /* nb_negative */ | 
					
						
							|  |  |  |      0,                       /* nb_positive */ | 
					
						
							|  |  |  |      0,                       /* nb_absolute */ | 
					
						
							|  |  |  |      0,                       /* nb_bool */ | 
					
						
							|  |  |  |      0,                       /* nb_invert */ | 
					
						
							|  |  |  |      0,                       /* nb_lshift */ | 
					
						
							|  |  |  |      0,                       /* nb_rshift */ | 
					
						
							|  |  |  |      0,                       /* nb_and */ | 
					
						
							|  |  |  |      0,                       /* nb_xor */ | 
					
						
							|  |  |  |      0,                       /* nb_or */ | 
					
						
							|  |  |  |      (unaryfunc)interpid_int, /* nb_int */ | 
					
						
							|  |  |  |      0,                       /* nb_reserved */ | 
					
						
							|  |  |  |      0,                       /* nb_float */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      0,                       /* nb_inplace_add */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_subtract */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_multiply */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_remainder */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_power */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_lshift */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_rshift */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_and */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_xor */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_or */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      0,                       /* nb_floor_divide */ | 
					
						
							|  |  |  |      0,                       /* nb_true_divide */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_floor_divide */ | 
					
						
							|  |  |  |      0,                       /* nb_inplace_true_divide */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      (unaryfunc)interpid_int, /* nb_index */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Py_hash_t | 
					
						
							|  |  |  | interpid_hash(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpid *id = (interpid *)self; | 
					
						
							|  |  |  |     PyObject *obj = PyLong_FromLongLong(id->id); | 
					
						
							|  |  |  |     if (obj == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_hash_t hash = PyObject_Hash(obj); | 
					
						
							|  |  |  |     Py_DECREF(obj); | 
					
						
							|  |  |  |     return hash; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | interpid_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (op != Py_EQ && op != Py_NE) { | 
					
						
							|  |  |  |         Py_RETURN_NOTIMPLEMENTED; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  |     if (!PyObject_TypeCheck(self, &PyInterpreterID_Type)) { | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |         Py_RETURN_NOTIMPLEMENTED; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     interpid *id = (interpid *)self; | 
					
						
							|  |  |  |     int equal; | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  |     if (PyObject_TypeCheck(other, &PyInterpreterID_Type)) { | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |         interpid *otherid = (interpid *)other; | 
					
						
							|  |  |  |         equal = (id->id == otherid->id); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-09-13 22:50:27 +03:00
										 |  |  |     else if (PyLong_CheckExact(other)) { | 
					
						
							|  |  |  |         /* Fast path */ | 
					
						
							|  |  |  |         int overflow; | 
					
						
							|  |  |  |         long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow); | 
					
						
							|  |  |  |         if (otherid == -1 && PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-09-13 22:50:27 +03:00
										 |  |  |         equal = !overflow && (otherid >= 0) && (id->id == otherid); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyNumber_Check(other)) { | 
					
						
							|  |  |  |         PyObject *pyid = PyLong_FromLongLong(id->id); | 
					
						
							|  |  |  |         if (pyid == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-09-13 22:50:27 +03:00
										 |  |  |         PyObject *res = PyObject_RichCompare(pyid, other, op); | 
					
						
							|  |  |  |         Py_DECREF(pyid); | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         Py_RETURN_NOTIMPLEMENTED; | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { | 
					
						
							|  |  |  |         Py_RETURN_TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(interpid_doc, | 
					
						
							|  |  |  | "A interpreter ID identifies a interpreter and may be used as an int."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  | PyTypeObject PyInterpreterID_Type = { | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |     "InterpreterID",   /* tp_name */ | 
					
						
							|  |  |  |     sizeof(interpid),               /* tp_basicsize */ | 
					
						
							|  |  |  |     0,                              /* tp_itemsize */ | 
					
						
							|  |  |  |     (destructor)interpid_dealloc,   /* tp_dealloc */ | 
					
						
							| 
									
										
										
										
											2019-05-31 04:13:39 +02:00
										 |  |  |     0,                              /* tp_vectorcall_offset */ | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     0,                              /* tp_getattr */ | 
					
						
							|  |  |  |     0,                              /* tp_setattr */ | 
					
						
							|  |  |  |     0,                              /* tp_as_async */ | 
					
						
							|  |  |  |     (reprfunc)interpid_repr,        /* tp_repr */ | 
					
						
							|  |  |  |     &interpid_as_number,            /* tp_as_number */ | 
					
						
							|  |  |  |     0,                              /* tp_as_sequence */ | 
					
						
							|  |  |  |     0,                              /* tp_as_mapping */ | 
					
						
							|  |  |  |     interpid_hash,                  /* tp_hash */ | 
					
						
							|  |  |  |     0,                              /* tp_call */ | 
					
						
							|  |  |  |     (reprfunc)interpid_str,         /* tp_str */ | 
					
						
							|  |  |  |     0,                              /* tp_getattro */ | 
					
						
							|  |  |  |     0,                              /* tp_setattro */ | 
					
						
							|  |  |  |     0,                              /* tp_as_buffer */ | 
					
						
							| 
									
										
										
										
											2019-09-13 22:50:27 +03:00
										 |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     interpid_doc,                   /* tp_doc */ | 
					
						
							|  |  |  |     0,                              /* tp_traverse */ | 
					
						
							|  |  |  |     0,                              /* tp_clear */ | 
					
						
							|  |  |  |     interpid_richcompare,           /* tp_richcompare */ | 
					
						
							|  |  |  |     0,                              /* tp_weaklistoffset */ | 
					
						
							|  |  |  |     0,                              /* tp_iter */ | 
					
						
							|  |  |  |     0,                              /* tp_iternext */ | 
					
						
							|  |  |  |     0,                              /* tp_methods */ | 
					
						
							|  |  |  |     0,                              /* tp_members */ | 
					
						
							|  |  |  |     0,                              /* tp_getset */ | 
					
						
							| 
									
										
										
										
											2019-09-13 22:50:27 +03:00
										 |  |  |     0,                              /* tp_base */ | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     0,                              /* tp_dict */ | 
					
						
							|  |  |  |     0,                              /* tp_descr_get */ | 
					
						
							|  |  |  |     0,                              /* tp_descr_set */ | 
					
						
							|  |  |  |     0,                              /* tp_dictoffset */ | 
					
						
							|  |  |  |     0,                              /* tp_init */ | 
					
						
							|  |  |  |     0,                              /* tp_alloc */ | 
					
						
							|  |  |  |     interpid_new,                   /* tp_new */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  | PyObject *PyInterpreterID_New(int64_t id) | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  |     return (PyObject *)newinterpid(&PyInterpreterID_Type, id, 0); | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  | PyInterpreterState_GetIDObject(PyInterpreterState *interp) | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | { | 
					
						
							|  |  |  |     if (_PyInterpreterState_IDInitref(interp) != 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2020-04-17 19:13:06 +02:00
										 |  |  |     int64_t id = PyInterpreterState_GetID(interp); | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  |     if (id < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-27 15:30:16 -06:00
										 |  |  |     return (PyObject *)newinterpid(&PyInterpreterID_Type, id, 0); | 
					
						
							| 
									
										
										
										
											2019-03-15 16:35:46 -06:00
										 |  |  | } |