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