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