Branch data Line data Source code
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 : :
9 : : typedef struct interpid {
10 : : PyObject_HEAD
11 : : int64_t id;
12 : : } interpid;
13 : :
14 : : static interpid *
15 : 469 : newinterpid(PyTypeObject *cls, int64_t id, int force)
16 : : {
17 : 469 : PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
18 [ + + ]: 469 : if (interp == NULL) {
19 [ + + ]: 5 : if (force) {
20 : 4 : PyErr_Clear();
21 : : }
22 : : else {
23 : 1 : return NULL;
24 : : }
25 : : }
26 : :
27 [ + + ]: 468 : if (interp != NULL) {
28 [ - + ]: 464 : if (_PyInterpreterState_IDIncref(interp) < 0) {
29 : 0 : return NULL;
30 : : }
31 : : }
32 : :
33 : 468 : interpid *self = PyObject_New(interpid, cls);
34 [ - + ]: 468 : if (self == NULL) {
35 [ # # ]: 0 : if (interp != NULL) {
36 : 0 : _PyInterpreterState_IDDecref(interp);
37 : : }
38 : 0 : return NULL;
39 : : }
40 : 468 : self->id = id;
41 : :
42 : 468 : return self;
43 : : }
44 : :
45 : : static int
46 : 157 : interp_id_converter(PyObject *arg, void *ptr)
47 : : {
48 : : int64_t id;
49 [ + + ]: 157 : if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
50 : 126 : id = ((interpid *)arg)->id;
51 : : }
52 [ + + ]: 31 : else if (_PyIndex_Check(arg)) {
53 : 26 : id = PyLong_AsLongLong(arg);
54 [ + + + + ]: 26 : if (id == -1 && PyErr_Occurred()) {
55 : 1 : return 0;
56 : : }
57 [ + + ]: 25 : if (id < 0) {
58 : 7 : PyErr_Format(PyExc_ValueError,
59 : : "interpreter ID must be a non-negative int, got %R", arg);
60 : 7 : return 0;
61 : : }
62 : : }
63 : : else {
64 : 5 : PyErr_Format(PyExc_TypeError,
65 : : "interpreter ID must be an int, got %.100s",
66 : 5 : Py_TYPE(arg)->tp_name);
67 : 5 : return 0;
68 : : }
69 : 144 : *(int64_t *)ptr = id;
70 : 144 : return 1;
71 : : }
72 : :
73 : : static PyObject *
74 : 12 : interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
75 : : {
76 : : static char *kwlist[] = {"id", "force", NULL};
77 : : int64_t id;
78 : 12 : int force = 0;
79 [ + + ]: 12 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
80 : : "O&|$p:InterpreterID.__init__", kwlist,
81 : : interp_id_converter, &id, &force)) {
82 : 6 : return NULL;
83 : : }
84 : :
85 : 6 : return (PyObject *)newinterpid(cls, id, force);
86 : : }
87 : :
88 : : static void
89 : 468 : interpid_dealloc(PyObject *v)
90 : : {
91 : 468 : int64_t id = ((interpid *)v)->id;
92 : 468 : PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
93 [ + + ]: 468 : if (interp != NULL) {
94 : 393 : _PyInterpreterState_IDDecref(interp);
95 : : }
96 : : else {
97 : : // already deleted
98 : 75 : PyErr_Clear();
99 : : }
100 : 468 : Py_TYPE(v)->tp_free(v);
101 : 468 : }
102 : :
103 : : static PyObject *
104 : 1 : interpid_repr(PyObject *self)
105 : : {
106 : 1 : PyTypeObject *type = Py_TYPE(self);
107 : 1 : const char *name = _PyType_Name(type);
108 : 1 : interpid *id = (interpid *)self;
109 : 1 : return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
110 : : }
111 : :
112 : : static PyObject *
113 : 14 : interpid_str(PyObject *self)
114 : : {
115 : 14 : interpid *id = (interpid *)self;
116 : 14 : return PyUnicode_FromFormat("%" PRId64 "", id->id);
117 : : }
118 : :
119 : : static PyObject *
120 : 10 : interpid_int(PyObject *self)
121 : : {
122 : 10 : interpid *id = (interpid *)self;
123 : 10 : 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 : 92 : interpid_hash(PyObject *self)
168 : : {
169 : 92 : interpid *id = (interpid *)self;
170 : 92 : PyObject *obj = PyLong_FromLongLong(id->id);
171 [ - + ]: 92 : if (obj == NULL) {
172 : 0 : return -1;
173 : : }
174 : 92 : Py_hash_t hash = PyObject_Hash(obj);
175 : 92 : Py_DECREF(obj);
176 : 92 : return hash;
177 : : }
178 : :
179 : : static PyObject *
180 : 357 : interpid_richcompare(PyObject *self, PyObject *other, int op)
181 : : {
182 [ + + - + ]: 357 : if (op != Py_EQ && op != Py_NE) {
183 : 0 : Py_RETURN_NOTIMPLEMENTED;
184 : : }
185 : :
186 [ - + ]: 357 : if (!PyObject_TypeCheck(self, &_PyInterpreterID_Type)) {
187 : 0 : Py_RETURN_NOTIMPLEMENTED;
188 : : }
189 : :
190 : 357 : interpid *id = (interpid *)self;
191 : : int equal;
192 [ + + ]: 357 : if (PyObject_TypeCheck(other, &_PyInterpreterID_Type)) {
193 : 142 : interpid *otherid = (interpid *)other;
194 : 142 : equal = (id->id == otherid->id);
195 : : }
196 [ + + ]: 215 : else if (PyLong_CheckExact(other)) {
197 : : /* Fast path */
198 : : int overflow;
199 : 208 : long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
200 [ + + - + ]: 208 : if (otherid == -1 && PyErr_Occurred()) {
201 : 0 : return NULL;
202 : : }
203 [ + + + - : 208 : equal = !overflow && (otherid >= 0) && (id->id == otherid);
+ + ]
204 : : }
205 [ + + ]: 7 : else if (PyNumber_Check(other)) {
206 : 4 : PyObject *pyid = PyLong_FromLongLong(id->id);
207 [ - + ]: 4 : if (pyid == NULL) {
208 : 0 : return NULL;
209 : : }
210 : 4 : PyObject *res = PyObject_RichCompare(pyid, other, op);
211 : 4 : Py_DECREF(pyid);
212 : 4 : return res;
213 : : }
214 : : else {
215 : 3 : Py_RETURN_NOTIMPLEMENTED;
216 : : }
217 : :
218 [ + + + + : 350 : if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
+ + + + ]
219 : 310 : Py_RETURN_TRUE;
220 : : }
221 : 40 : 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 : 20 : PyObject *_PyInterpreterID_New(int64_t id)
269 : : {
270 : 20 : return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
271 : : }
272 : :
273 : : PyObject *
274 : 443 : _PyInterpreterState_GetIDObject(PyInterpreterState *interp)
275 : : {
276 [ - + ]: 443 : if (_PyInterpreterState_IDInitref(interp) != 0) {
277 : 0 : return NULL;
278 : : };
279 : 443 : int64_t id = PyInterpreterState_GetID(interp);
280 [ - + ]: 443 : if (id < 0) {
281 : 0 : return NULL;
282 : : }
283 : 443 : return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
284 : : }
285 : :
286 : : PyInterpreterState *
287 : 145 : _PyInterpreterID_LookUp(PyObject *requested_id)
288 : : {
289 : : int64_t id;
290 [ + + ]: 145 : if (!interp_id_converter(requested_id, &id)) {
291 : 7 : return NULL;
292 : : }
293 : 138 : return _PyInterpreterState_LookUpID(id);
294 : : }
|