(root)/
Python-3.12.0/
Objects/
interpreteridobject.c
       1  /* InterpreterID object */
       2  
       3  #include "Python.h"
       4  #include "pycore_abstract.h"   // _PyIndex_Check()
       5  #include "pycore_interp.h"     // _PyInterpreterState_LookUpID()
       6  #include "interpreteridobject.h"
       7  
       8  
       9  typedef struct interpid {
      10      PyObject_HEAD
      11      int64_t id;
      12  } interpid;
      13  
      14  static interpid *
      15  newinterpid(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  
      45  static int
      46  interp_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  
      73  static PyObject *
      74  interpid_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  
      88  static void
      89  interpid_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  
     103  static PyObject *
     104  interpid_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  
     112  static PyObject *
     113  interpid_str(PyObject *self)
     114  {
     115      interpid *id = (interpid *)self;
     116      return PyUnicode_FromFormat("%" PRId64 "", id->id);
     117  }
     118  
     119  static PyObject *
     120  interpid_int(PyObject *self)
     121  {
     122      interpid *id = (interpid *)self;
     123      return PyLong_FromLongLong(id->id);
     124  }
     125  
     126  static 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  
     166  static Py_hash_t
     167  interpid_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  
     179  static PyObject *
     180  interpid_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  
     224  PyDoc_STRVAR(interpid_doc,
     225  "A interpreter ID identifies a interpreter and may be used as an int.");
     226  
     227  PyTypeObject _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  
     268  PyObject *_PyInterpreterID_New(int64_t id)
     269  {
     270      return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
     271  }
     272  
     273  PyObject *
     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  
     286  PyInterpreterState *
     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  }