17db96d56Sopenharmony_ci/* InterpreterID object */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci#include "Python.h"
47db96d56Sopenharmony_ci#include "pycore_abstract.h"   // _PyIndex_Check()
57db96d56Sopenharmony_ci#include "pycore_interp.h"     // _PyInterpreterState_LookUpID()
67db96d56Sopenharmony_ci#include "pycore_interpreteridobject.h"
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_citypedef struct interpid {
107db96d56Sopenharmony_ci    PyObject_HEAD
117db96d56Sopenharmony_ci    int64_t id;
127db96d56Sopenharmony_ci} interpid;
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_cistatic interpid *
157db96d56Sopenharmony_cinewinterpid(PyTypeObject *cls, int64_t id, int force)
167db96d56Sopenharmony_ci{
177db96d56Sopenharmony_ci    PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
187db96d56Sopenharmony_ci    if (interp == NULL) {
197db96d56Sopenharmony_ci        if (force) {
207db96d56Sopenharmony_ci            PyErr_Clear();
217db96d56Sopenharmony_ci        }
227db96d56Sopenharmony_ci        else {
237db96d56Sopenharmony_ci            return NULL;
247db96d56Sopenharmony_ci        }
257db96d56Sopenharmony_ci    }
267db96d56Sopenharmony_ci
277db96d56Sopenharmony_ci    if (interp != NULL) {
287db96d56Sopenharmony_ci        if (_PyInterpreterState_IDIncref(interp) < 0) {
297db96d56Sopenharmony_ci            return NULL;
307db96d56Sopenharmony_ci        }
317db96d56Sopenharmony_ci    }
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci    interpid *self = PyObject_New(interpid, cls);
347db96d56Sopenharmony_ci    if (self == NULL) {
357db96d56Sopenharmony_ci        if (interp != NULL) {
367db96d56Sopenharmony_ci            _PyInterpreterState_IDDecref(interp);
377db96d56Sopenharmony_ci        }
387db96d56Sopenharmony_ci        return NULL;
397db96d56Sopenharmony_ci    }
407db96d56Sopenharmony_ci    self->id = id;
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci    return self;
437db96d56Sopenharmony_ci}
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_cistatic int
467db96d56Sopenharmony_ciinterp_id_converter(PyObject *arg, void *ptr)
477db96d56Sopenharmony_ci{
487db96d56Sopenharmony_ci    int64_t id;
497db96d56Sopenharmony_ci    if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
507db96d56Sopenharmony_ci        id = ((interpid *)arg)->id;
517db96d56Sopenharmony_ci    }
527db96d56Sopenharmony_ci    else if (_PyIndex_Check(arg)) {
537db96d56Sopenharmony_ci        id = PyLong_AsLongLong(arg);
547db96d56Sopenharmony_ci        if (id == -1 && PyErr_Occurred()) {
557db96d56Sopenharmony_ci            return 0;
567db96d56Sopenharmony_ci        }
577db96d56Sopenharmony_ci        if (id < 0) {
587db96d56Sopenharmony_ci            PyErr_Format(PyExc_ValueError,
597db96d56Sopenharmony_ci                         "interpreter ID must be a non-negative int, got %R", arg);
607db96d56Sopenharmony_ci            return 0;
617db96d56Sopenharmony_ci        }
627db96d56Sopenharmony_ci    }
637db96d56Sopenharmony_ci    else {
647db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
657db96d56Sopenharmony_ci                     "interpreter ID must be an int, got %.100s",
667db96d56Sopenharmony_ci                     Py_TYPE(arg)->tp_name);
677db96d56Sopenharmony_ci        return 0;
687db96d56Sopenharmony_ci    }
697db96d56Sopenharmony_ci    *(int64_t *)ptr = id;
707db96d56Sopenharmony_ci    return 1;
717db96d56Sopenharmony_ci}
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_cistatic PyObject *
747db96d56Sopenharmony_ciinterpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
757db96d56Sopenharmony_ci{
767db96d56Sopenharmony_ci    static char *kwlist[] = {"id", "force", NULL};
777db96d56Sopenharmony_ci    int64_t id;
787db96d56Sopenharmony_ci    int force = 0;
797db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwds,
807db96d56Sopenharmony_ci                                     "O&|$p:InterpreterID.__init__", kwlist,
817db96d56Sopenharmony_ci                                     interp_id_converter, &id, &force)) {
827db96d56Sopenharmony_ci        return NULL;
837db96d56Sopenharmony_ci    }
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci    return (PyObject *)newinterpid(cls, id, force);
867db96d56Sopenharmony_ci}
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_cistatic void
897db96d56Sopenharmony_ciinterpid_dealloc(PyObject *v)
907db96d56Sopenharmony_ci{
917db96d56Sopenharmony_ci    int64_t id = ((interpid *)v)->id;
927db96d56Sopenharmony_ci    PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
937db96d56Sopenharmony_ci    if (interp != NULL) {
947db96d56Sopenharmony_ci        _PyInterpreterState_IDDecref(interp);
957db96d56Sopenharmony_ci    }
967db96d56Sopenharmony_ci    else {
977db96d56Sopenharmony_ci        // already deleted
987db96d56Sopenharmony_ci        PyErr_Clear();
997db96d56Sopenharmony_ci    }
1007db96d56Sopenharmony_ci    Py_TYPE(v)->tp_free(v);
1017db96d56Sopenharmony_ci}
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_cistatic PyObject *
1047db96d56Sopenharmony_ciinterpid_repr(PyObject *self)
1057db96d56Sopenharmony_ci{
1067db96d56Sopenharmony_ci    PyTypeObject *type = Py_TYPE(self);
1077db96d56Sopenharmony_ci    const char *name = _PyType_Name(type);
1087db96d56Sopenharmony_ci    interpid *id = (interpid *)self;
1097db96d56Sopenharmony_ci    return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
1107db96d56Sopenharmony_ci}
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_cistatic PyObject *
1137db96d56Sopenharmony_ciinterpid_str(PyObject *self)
1147db96d56Sopenharmony_ci{
1157db96d56Sopenharmony_ci    interpid *id = (interpid *)self;
1167db96d56Sopenharmony_ci    return PyUnicode_FromFormat("%" PRId64 "", id->id);
1177db96d56Sopenharmony_ci}
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_cistatic PyObject *
1207db96d56Sopenharmony_ciinterpid_int(PyObject *self)
1217db96d56Sopenharmony_ci{
1227db96d56Sopenharmony_ci    interpid *id = (interpid *)self;
1237db96d56Sopenharmony_ci    return PyLong_FromLongLong(id->id);
1247db96d56Sopenharmony_ci}
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_cistatic PyNumberMethods interpid_as_number = {
1277db96d56Sopenharmony_ci     0,                       /* nb_add */
1287db96d56Sopenharmony_ci     0,                       /* nb_subtract */
1297db96d56Sopenharmony_ci     0,                       /* nb_multiply */
1307db96d56Sopenharmony_ci     0,                       /* nb_remainder */
1317db96d56Sopenharmony_ci     0,                       /* nb_divmod */
1327db96d56Sopenharmony_ci     0,                       /* nb_power */
1337db96d56Sopenharmony_ci     0,                       /* nb_negative */
1347db96d56Sopenharmony_ci     0,                       /* nb_positive */
1357db96d56Sopenharmony_ci     0,                       /* nb_absolute */
1367db96d56Sopenharmony_ci     0,                       /* nb_bool */
1377db96d56Sopenharmony_ci     0,                       /* nb_invert */
1387db96d56Sopenharmony_ci     0,                       /* nb_lshift */
1397db96d56Sopenharmony_ci     0,                       /* nb_rshift */
1407db96d56Sopenharmony_ci     0,                       /* nb_and */
1417db96d56Sopenharmony_ci     0,                       /* nb_xor */
1427db96d56Sopenharmony_ci     0,                       /* nb_or */
1437db96d56Sopenharmony_ci     (unaryfunc)interpid_int, /* nb_int */
1447db96d56Sopenharmony_ci     0,                       /* nb_reserved */
1457db96d56Sopenharmony_ci     0,                       /* nb_float */
1467db96d56Sopenharmony_ci
1477db96d56Sopenharmony_ci     0,                       /* nb_inplace_add */
1487db96d56Sopenharmony_ci     0,                       /* nb_inplace_subtract */
1497db96d56Sopenharmony_ci     0,                       /* nb_inplace_multiply */
1507db96d56Sopenharmony_ci     0,                       /* nb_inplace_remainder */
1517db96d56Sopenharmony_ci     0,                       /* nb_inplace_power */
1527db96d56Sopenharmony_ci     0,                       /* nb_inplace_lshift */
1537db96d56Sopenharmony_ci     0,                       /* nb_inplace_rshift */
1547db96d56Sopenharmony_ci     0,                       /* nb_inplace_and */
1557db96d56Sopenharmony_ci     0,                       /* nb_inplace_xor */
1567db96d56Sopenharmony_ci     0,                       /* nb_inplace_or */
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_ci     0,                       /* nb_floor_divide */
1597db96d56Sopenharmony_ci     0,                       /* nb_true_divide */
1607db96d56Sopenharmony_ci     0,                       /* nb_inplace_floor_divide */
1617db96d56Sopenharmony_ci     0,                       /* nb_inplace_true_divide */
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci     (unaryfunc)interpid_int, /* nb_index */
1647db96d56Sopenharmony_ci};
1657db96d56Sopenharmony_ci
1667db96d56Sopenharmony_cistatic Py_hash_t
1677db96d56Sopenharmony_ciinterpid_hash(PyObject *self)
1687db96d56Sopenharmony_ci{
1697db96d56Sopenharmony_ci    interpid *id = (interpid *)self;
1707db96d56Sopenharmony_ci    PyObject *obj = PyLong_FromLongLong(id->id);
1717db96d56Sopenharmony_ci    if (obj == NULL) {
1727db96d56Sopenharmony_ci        return -1;
1737db96d56Sopenharmony_ci    }
1747db96d56Sopenharmony_ci    Py_hash_t hash = PyObject_Hash(obj);
1757db96d56Sopenharmony_ci    Py_DECREF(obj);
1767db96d56Sopenharmony_ci    return hash;
1777db96d56Sopenharmony_ci}
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_cistatic PyObject *
1807db96d56Sopenharmony_ciinterpid_richcompare(PyObject *self, PyObject *other, int op)
1817db96d56Sopenharmony_ci{
1827db96d56Sopenharmony_ci    if (op != Py_EQ && op != Py_NE) {
1837db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
1847db96d56Sopenharmony_ci    }
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci    if (!PyObject_TypeCheck(self, &_PyInterpreterID_Type)) {
1877db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
1887db96d56Sopenharmony_ci    }
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ci    interpid *id = (interpid *)self;
1917db96d56Sopenharmony_ci    int equal;
1927db96d56Sopenharmony_ci    if (PyObject_TypeCheck(other, &_PyInterpreterID_Type)) {
1937db96d56Sopenharmony_ci        interpid *otherid = (interpid *)other;
1947db96d56Sopenharmony_ci        equal = (id->id == otherid->id);
1957db96d56Sopenharmony_ci    }
1967db96d56Sopenharmony_ci    else if (PyLong_CheckExact(other)) {
1977db96d56Sopenharmony_ci        /* Fast path */
1987db96d56Sopenharmony_ci        int overflow;
1997db96d56Sopenharmony_ci        long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
2007db96d56Sopenharmony_ci        if (otherid == -1 && PyErr_Occurred()) {
2017db96d56Sopenharmony_ci            return NULL;
2027db96d56Sopenharmony_ci        }
2037db96d56Sopenharmony_ci        equal = !overflow && (otherid >= 0) && (id->id == otherid);
2047db96d56Sopenharmony_ci    }
2057db96d56Sopenharmony_ci    else if (PyNumber_Check(other)) {
2067db96d56Sopenharmony_ci        PyObject *pyid = PyLong_FromLongLong(id->id);
2077db96d56Sopenharmony_ci        if (pyid == NULL) {
2087db96d56Sopenharmony_ci            return NULL;
2097db96d56Sopenharmony_ci        }
2107db96d56Sopenharmony_ci        PyObject *res = PyObject_RichCompare(pyid, other, op);
2117db96d56Sopenharmony_ci        Py_DECREF(pyid);
2127db96d56Sopenharmony_ci        return res;
2137db96d56Sopenharmony_ci    }
2147db96d56Sopenharmony_ci    else {
2157db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
2167db96d56Sopenharmony_ci    }
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ci    if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
2197db96d56Sopenharmony_ci        Py_RETURN_TRUE;
2207db96d56Sopenharmony_ci    }
2217db96d56Sopenharmony_ci    Py_RETURN_FALSE;
2227db96d56Sopenharmony_ci}
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ciPyDoc_STRVAR(interpid_doc,
2257db96d56Sopenharmony_ci"A interpreter ID identifies a interpreter and may be used as an int.");
2267db96d56Sopenharmony_ci
2277db96d56Sopenharmony_ciPyTypeObject _PyInterpreterID_Type = {
2287db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2297db96d56Sopenharmony_ci    "InterpreterID",   /* tp_name */
2307db96d56Sopenharmony_ci    sizeof(interpid),               /* tp_basicsize */
2317db96d56Sopenharmony_ci    0,                              /* tp_itemsize */
2327db96d56Sopenharmony_ci    (destructor)interpid_dealloc,   /* tp_dealloc */
2337db96d56Sopenharmony_ci    0,                              /* tp_vectorcall_offset */
2347db96d56Sopenharmony_ci    0,                              /* tp_getattr */
2357db96d56Sopenharmony_ci    0,                              /* tp_setattr */
2367db96d56Sopenharmony_ci    0,                              /* tp_as_async */
2377db96d56Sopenharmony_ci    (reprfunc)interpid_repr,        /* tp_repr */
2387db96d56Sopenharmony_ci    &interpid_as_number,            /* tp_as_number */
2397db96d56Sopenharmony_ci    0,                              /* tp_as_sequence */
2407db96d56Sopenharmony_ci    0,                              /* tp_as_mapping */
2417db96d56Sopenharmony_ci    interpid_hash,                  /* tp_hash */
2427db96d56Sopenharmony_ci    0,                              /* tp_call */
2437db96d56Sopenharmony_ci    (reprfunc)interpid_str,         /* tp_str */
2447db96d56Sopenharmony_ci    0,                              /* tp_getattro */
2457db96d56Sopenharmony_ci    0,                              /* tp_setattro */
2467db96d56Sopenharmony_ci    0,                              /* tp_as_buffer */
2477db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2487db96d56Sopenharmony_ci    interpid_doc,                   /* tp_doc */
2497db96d56Sopenharmony_ci    0,                              /* tp_traverse */
2507db96d56Sopenharmony_ci    0,                              /* tp_clear */
2517db96d56Sopenharmony_ci    interpid_richcompare,           /* tp_richcompare */
2527db96d56Sopenharmony_ci    0,                              /* tp_weaklistoffset */
2537db96d56Sopenharmony_ci    0,                              /* tp_iter */
2547db96d56Sopenharmony_ci    0,                              /* tp_iternext */
2557db96d56Sopenharmony_ci    0,                              /* tp_methods */
2567db96d56Sopenharmony_ci    0,                              /* tp_members */
2577db96d56Sopenharmony_ci    0,                              /* tp_getset */
2587db96d56Sopenharmony_ci    0,                              /* tp_base */
2597db96d56Sopenharmony_ci    0,                              /* tp_dict */
2607db96d56Sopenharmony_ci    0,                              /* tp_descr_get */
2617db96d56Sopenharmony_ci    0,                              /* tp_descr_set */
2627db96d56Sopenharmony_ci    0,                              /* tp_dictoffset */
2637db96d56Sopenharmony_ci    0,                              /* tp_init */
2647db96d56Sopenharmony_ci    0,                              /* tp_alloc */
2657db96d56Sopenharmony_ci    interpid_new,                   /* tp_new */
2667db96d56Sopenharmony_ci};
2677db96d56Sopenharmony_ci
2687db96d56Sopenharmony_ciPyObject *_PyInterpreterID_New(int64_t id)
2697db96d56Sopenharmony_ci{
2707db96d56Sopenharmony_ci    return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
2717db96d56Sopenharmony_ci}
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ciPyObject *
2747db96d56Sopenharmony_ci_PyInterpreterState_GetIDObject(PyInterpreterState *interp)
2757db96d56Sopenharmony_ci{
2767db96d56Sopenharmony_ci    if (_PyInterpreterState_IDInitref(interp) != 0) {
2777db96d56Sopenharmony_ci        return NULL;
2787db96d56Sopenharmony_ci    };
2797db96d56Sopenharmony_ci    int64_t id = PyInterpreterState_GetID(interp);
2807db96d56Sopenharmony_ci    if (id < 0) {
2817db96d56Sopenharmony_ci        return NULL;
2827db96d56Sopenharmony_ci    }
2837db96d56Sopenharmony_ci    return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
2847db96d56Sopenharmony_ci}
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ciPyInterpreterState *
2877db96d56Sopenharmony_ci_PyInterpreterID_LookUp(PyObject *requested_id)
2887db96d56Sopenharmony_ci{
2897db96d56Sopenharmony_ci    int64_t id;
2907db96d56Sopenharmony_ci    if (!interp_id_converter(requested_id, &id)) {
2917db96d56Sopenharmony_ci        return NULL;
2927db96d56Sopenharmony_ci    }
2937db96d56Sopenharmony_ci    return _PyInterpreterState_LookUpID(id);
2947db96d56Sopenharmony_ci}
295