1/* InterpreterID object */ 2 3#include "Python.h" 4#include "pycore_abstract.h" // _PyIndex_Check() 5#include "pycore_interp.h" // _PyInterpreterState_LookUpID() 6#include "pycore_interpreteridobject.h" 7 8 9typedef struct interpid { 10 PyObject_HEAD 11 int64_t id; 12} interpid; 13 14static interpid * 15newinterpid(PyTypeObject *cls, int64_t id, int force) 16{ 17 PyInterpreterState *interp = _PyInterpreterState_LookUpID(id); 18 if (interp == NULL) { 19 if (force) { 20 PyErr_Clear(); 21 } 22 else { 23 return NULL; 24 } 25 } 26 27 if (interp != NULL) { 28 if (_PyInterpreterState_IDIncref(interp) < 0) { 29 return NULL; 30 } 31 } 32 33 interpid *self = PyObject_New(interpid, cls); 34 if (self == NULL) { 35 if (interp != NULL) { 36 _PyInterpreterState_IDDecref(interp); 37 } 38 return NULL; 39 } 40 self->id = id; 41 42 return self; 43} 44 45static int 46interp_id_converter(PyObject *arg, void *ptr) 47{ 48 int64_t id; 49 if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) { 50 id = ((interpid *)arg)->id; 51 } 52 else if (_PyIndex_Check(arg)) { 53 id = PyLong_AsLongLong(arg); 54 if (id == -1 && PyErr_Occurred()) { 55 return 0; 56 } 57 if (id < 0) { 58 PyErr_Format(PyExc_ValueError, 59 "interpreter ID must be a non-negative int, got %R", arg); 60 return 0; 61 } 62 } 63 else { 64 PyErr_Format(PyExc_TypeError, 65 "interpreter ID must be an int, got %.100s", 66 Py_TYPE(arg)->tp_name); 67 return 0; 68 } 69 *(int64_t *)ptr = id; 70 return 1; 71} 72 73static PyObject * 74interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) 75{ 76 static char *kwlist[] = {"id", "force", NULL}; 77 int64_t id; 78 int force = 0; 79 if (!PyArg_ParseTupleAndKeywords(args, kwds, 80 "O&|$p:InterpreterID.__init__", kwlist, 81 interp_id_converter, &id, &force)) { 82 return NULL; 83 } 84 85 return (PyObject *)newinterpid(cls, id, force); 86} 87 88static void 89interpid_dealloc(PyObject *v) 90{ 91 int64_t id = ((interpid *)v)->id; 92 PyInterpreterState *interp = _PyInterpreterState_LookUpID(id); 93 if (interp != NULL) { 94 _PyInterpreterState_IDDecref(interp); 95 } 96 else { 97 // already deleted 98 PyErr_Clear(); 99 } 100 Py_TYPE(v)->tp_free(v); 101} 102 103static PyObject * 104interpid_repr(PyObject *self) 105{ 106 PyTypeObject *type = Py_TYPE(self); 107 const char *name = _PyType_Name(type); 108 interpid *id = (interpid *)self; 109 return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id); 110} 111 112static PyObject * 113interpid_str(PyObject *self) 114{ 115 interpid *id = (interpid *)self; 116 return PyUnicode_FromFormat("%" PRId64 "", id->id); 117} 118 119static PyObject * 120interpid_int(PyObject *self) 121{ 122 interpid *id = (interpid *)self; 123 return PyLong_FromLongLong(id->id); 124} 125 126static PyNumberMethods interpid_as_number = { 127 0, /* nb_add */ 128 0, /* nb_subtract */ 129 0, /* nb_multiply */ 130 0, /* nb_remainder */ 131 0, /* nb_divmod */ 132 0, /* nb_power */ 133 0, /* nb_negative */ 134 0, /* nb_positive */ 135 0, /* nb_absolute */ 136 0, /* nb_bool */ 137 0, /* nb_invert */ 138 0, /* nb_lshift */ 139 0, /* nb_rshift */ 140 0, /* nb_and */ 141 0, /* nb_xor */ 142 0, /* nb_or */ 143 (unaryfunc)interpid_int, /* nb_int */ 144 0, /* nb_reserved */ 145 0, /* nb_float */ 146 147 0, /* nb_inplace_add */ 148 0, /* nb_inplace_subtract */ 149 0, /* nb_inplace_multiply */ 150 0, /* nb_inplace_remainder */ 151 0, /* nb_inplace_power */ 152 0, /* nb_inplace_lshift */ 153 0, /* nb_inplace_rshift */ 154 0, /* nb_inplace_and */ 155 0, /* nb_inplace_xor */ 156 0, /* nb_inplace_or */ 157 158 0, /* nb_floor_divide */ 159 0, /* nb_true_divide */ 160 0, /* nb_inplace_floor_divide */ 161 0, /* nb_inplace_true_divide */ 162 163 (unaryfunc)interpid_int, /* nb_index */ 164}; 165 166static Py_hash_t 167interpid_hash(PyObject *self) 168{ 169 interpid *id = (interpid *)self; 170 PyObject *obj = PyLong_FromLongLong(id->id); 171 if (obj == NULL) { 172 return -1; 173 } 174 Py_hash_t hash = PyObject_Hash(obj); 175 Py_DECREF(obj); 176 return hash; 177} 178 179static PyObject * 180interpid_richcompare(PyObject *self, PyObject *other, int op) 181{ 182 if (op != Py_EQ && op != Py_NE) { 183 Py_RETURN_NOTIMPLEMENTED; 184 } 185 186 if (!PyObject_TypeCheck(self, &_PyInterpreterID_Type)) { 187 Py_RETURN_NOTIMPLEMENTED; 188 } 189 190 interpid *id = (interpid *)self; 191 int equal; 192 if (PyObject_TypeCheck(other, &_PyInterpreterID_Type)) { 193 interpid *otherid = (interpid *)other; 194 equal = (id->id == otherid->id); 195 } 196 else if (PyLong_CheckExact(other)) { 197 /* Fast path */ 198 int overflow; 199 long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow); 200 if (otherid == -1 && PyErr_Occurred()) { 201 return NULL; 202 } 203 equal = !overflow && (otherid >= 0) && (id->id == otherid); 204 } 205 else if (PyNumber_Check(other)) { 206 PyObject *pyid = PyLong_FromLongLong(id->id); 207 if (pyid == NULL) { 208 return NULL; 209 } 210 PyObject *res = PyObject_RichCompare(pyid, other, op); 211 Py_DECREF(pyid); 212 return res; 213 } 214 else { 215 Py_RETURN_NOTIMPLEMENTED; 216 } 217 218 if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { 219 Py_RETURN_TRUE; 220 } 221 Py_RETURN_FALSE; 222} 223 224PyDoc_STRVAR(interpid_doc, 225"A interpreter ID identifies a interpreter and may be used as an int."); 226 227PyTypeObject _PyInterpreterID_Type = { 228 PyVarObject_HEAD_INIT(&PyType_Type, 0) 229 "InterpreterID", /* tp_name */ 230 sizeof(interpid), /* tp_basicsize */ 231 0, /* tp_itemsize */ 232 (destructor)interpid_dealloc, /* tp_dealloc */ 233 0, /* tp_vectorcall_offset */ 234 0, /* tp_getattr */ 235 0, /* tp_setattr */ 236 0, /* tp_as_async */ 237 (reprfunc)interpid_repr, /* tp_repr */ 238 &interpid_as_number, /* tp_as_number */ 239 0, /* tp_as_sequence */ 240 0, /* tp_as_mapping */ 241 interpid_hash, /* tp_hash */ 242 0, /* tp_call */ 243 (reprfunc)interpid_str, /* tp_str */ 244 0, /* tp_getattro */ 245 0, /* tp_setattro */ 246 0, /* tp_as_buffer */ 247 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 248 interpid_doc, /* tp_doc */ 249 0, /* tp_traverse */ 250 0, /* tp_clear */ 251 interpid_richcompare, /* tp_richcompare */ 252 0, /* tp_weaklistoffset */ 253 0, /* tp_iter */ 254 0, /* tp_iternext */ 255 0, /* tp_methods */ 256 0, /* tp_members */ 257 0, /* tp_getset */ 258 0, /* tp_base */ 259 0, /* tp_dict */ 260 0, /* tp_descr_get */ 261 0, /* tp_descr_set */ 262 0, /* tp_dictoffset */ 263 0, /* tp_init */ 264 0, /* tp_alloc */ 265 interpid_new, /* tp_new */ 266}; 267 268PyObject *_PyInterpreterID_New(int64_t id) 269{ 270 return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0); 271} 272 273PyObject * 274_PyInterpreterState_GetIDObject(PyInterpreterState *interp) 275{ 276 if (_PyInterpreterState_IDInitref(interp) != 0) { 277 return NULL; 278 }; 279 int64_t id = PyInterpreterState_GetID(interp); 280 if (id < 0) { 281 return NULL; 282 } 283 return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0); 284} 285 286PyInterpreterState * 287_PyInterpreterID_LookUp(PyObject *requested_id) 288{ 289 int64_t id; 290 if (!interp_id_converter(requested_id, &id)) { 291 return NULL; 292 } 293 return _PyInterpreterState_LookUpID(id); 294} 295