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