• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
newinterpid(PyTypeObject * cls,int64_t id,int force)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
interp_id_converter(PyObject * arg,void * ptr)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 *
interpid_new(PyTypeObject * cls,PyObject * args,PyObject * kwds)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
interpid_dealloc(PyObject * v)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 *
interpid_repr(PyObject * self)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 *
interpid_str(PyObject * self)113 interpid_str(PyObject *self)
114 {
115     interpid *id = (interpid *)self;
116     return PyUnicode_FromFormat("%" PRId64 "", id->id);
117 }
118 
119 static PyObject *
interpid_int(PyObject * self)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
interpid_hash(PyObject * self)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 *
interpid_richcompare(PyObject * self,PyObject * other,int op)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 
_PyInterpreterID_New(int64_t id)268 PyObject *_PyInterpreterID_New(int64_t id)
269 {
270     return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
271 }
272 
273 PyObject *
_PyInterpreterState_GetIDObject(PyInterpreterState * interp)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 *
_PyInterpreterID_LookUp(PyObject * requested_id)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