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