blob: 3edbb85e6ac3b2ce761b9130e239fa6fca4f268d [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
Eric Snowc11183c2019-03-15 16:35:46 -06008typedef struct interpid {
9 PyObject_HEAD
10 int64_t id;
11} interpid;
12
13static interpid *
14newinterpid(PyTypeObject *cls, int64_t id, int force)
15{
16 PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
17 if (interp == NULL) {
18 if (force) {
19 PyErr_Clear();
20 }
21 else {
22 return NULL;
23 }
24 }
25
26 interpid *self = PyObject_New(interpid, cls);
27 if (self == NULL) {
28 return NULL;
29 }
30 self->id = id;
31
32 if (interp != NULL) {
33 _PyInterpreterState_IDIncref(interp);
34 }
35 return self;
36}
37
38static PyObject *
39interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
40{
41 static char *kwlist[] = {"id", "force", NULL};
42 PyObject *idobj;
43 int force = 0;
44 if (!PyArg_ParseTupleAndKeywords(args, kwds,
45 "O|$p:InterpreterID.__init__", kwlist,
46 &idobj, &force)) {
47 return NULL;
48 }
49
50 // Coerce and check the ID.
51 int64_t id;
52 if (PyObject_TypeCheck(idobj, &_PyInterpreterID_Type)) {
53 id = ((interpid *)idobj)->id;
54 }
55 else {
Serhiy Storchakaf37a9832019-09-14 19:36:19 +030056 PyObject *pyid;
57 if (PyIndex_Check(idobj)) {
58 pyid = idobj;
59 Py_INCREF(pyid);
60 }
61 else if (PyUnicode_Check(idobj)) {
62 pyid = PyNumber_Long(idobj);
63 if (pyid == NULL) {
64 return NULL;
65 }
66 }
67 else {
68 PyErr_Format(PyExc_TypeError,
69 "interpreter ID must be an int, got %.100s",
70 idobj->ob_type->tp_name);
71 return NULL;
72 }
73 id = PyLong_AsLongLong(pyid);
74 Py_DECREF(pyid);
75 if (id == -1 && PyErr_Occurred()) {
76 return NULL;
77 }
Eric Snowc11183c2019-03-15 16:35:46 -060078 if (id < 0) {
Serhiy Storchakaf37a9832019-09-14 19:36:19 +030079 PyErr_Format(PyExc_ValueError,
80 "interpreter ID must be a non-negative int, got %R", idobj);
Eric Snowc11183c2019-03-15 16:35:46 -060081 return NULL;
82 }
83 }
84
85 return (PyObject *)newinterpid(cls, id, force);
86}
87
88static void
89interpid_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
103static PyObject *
104interpid_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
112static PyObject *
113interpid_str(PyObject *self)
114{
115 interpid *id = (interpid *)self;
116 return PyUnicode_FromFormat("%" PRId64 "", id->id);
117}
118
119static PyObject *
120interpid_int(PyObject *self)
121{
122 interpid *id = (interpid *)self;
123 return PyLong_FromLongLong(id->id);
124}
125
126static 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
166static Py_hash_t
167interpid_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
179static PyObject *
180interpid_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 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300196 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()) {
Eric Snowc11183c2019-03-15 16:35:46 -0600201 return NULL;
202 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300203 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;
Eric Snowc11183c2019-03-15 16:35:46 -0600209 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300210 PyObject *res = PyObject_RichCompare(pyid, other, op);
211 Py_DECREF(pyid);
212 return res;
213 }
214 else {
215 Py_RETURN_NOTIMPLEMENTED;
Eric Snowc11183c2019-03-15 16:35:46 -0600216 }
217
218 if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
219 Py_RETURN_TRUE;
220 }
221 Py_RETURN_FALSE;
222}
223
224PyDoc_STRVAR(interpid_doc,
225"A interpreter ID identifies a interpreter and may be used as an int.");
226
227PyTypeObject _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 */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200233 0, /* tp_vectorcall_offset */
Eric Snowc11183c2019-03-15 16:35:46 -0600234 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 */
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300247 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
Eric Snowc11183c2019-03-15 16:35:46 -0600248 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 */
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300258 0, /* tp_base */
Eric Snowc11183c2019-03-15 16:35:46 -0600259 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
268PyObject *_PyInterpreterID_New(int64_t id)
269{
270 return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
271}
272
273PyObject *
274_PyInterpreterState_GetIDObject(PyInterpreterState *interp)
275{
276 if (_PyInterpreterState_IDInitref(interp) != 0) {
277 return NULL;
278 };
279 PY_INT64_T id = PyInterpreterState_GetID(interp);
280 if (id < 0) {
281 return NULL;
282 }
283 return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
284}
285
286PyInterpreterState *
287_PyInterpreterID_LookUp(PyObject *requested_id)
288{
289 int64_t id;
290 if (PyObject_TypeCheck(requested_id, &_PyInterpreterID_Type)) {
291 id = ((interpid *)requested_id)->id;
292 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300293 else if (PyIndex_Check(requested_id)) {
Eric Snowc11183c2019-03-15 16:35:46 -0600294 id = PyLong_AsLongLong(requested_id);
295 if (id == -1 && PyErr_Occurred() != NULL) {
296 return NULL;
297 }
298 assert(id <= INT64_MAX);
299 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300300 else {
301 PyErr_Format(PyExc_TypeError, "interpreter ID must be an int, got %.100s",
302 requested_id->ob_type->tp_name);
303 return NULL;
304 }
Eric Snowc11183c2019-03-15 16:35:46 -0600305 return _PyInterpreterState_LookUpID(id);
306}