blob: 94f5dd709bbda0906cb013712950bef5e928812b [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
Miss Islington (bot)ca14f042019-09-25 08:56:05 -070038static int
39interp_id_converter(PyObject *arg, void *ptr)
40{
41 int64_t id;
42 if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
43 id = ((interpid *)arg)->id;
44 }
45 else if (PyIndex_Check(arg)) {
46 id = PyLong_AsLongLong(arg);
47 if (id == -1 && PyErr_Occurred()) {
48 return 0;
49 }
50 if (id < 0) {
51 PyErr_Format(PyExc_ValueError,
52 "interpreter ID must be a non-negative int, got %R", arg);
53 return 0;
54 }
55 }
56 else {
57 PyErr_Format(PyExc_TypeError,
58 "interpreter ID must be an int, got %.100s",
59 arg->ob_type->tp_name);
60 return 0;
61 }
62 *(int64_t *)ptr = id;
63 return 1;
64}
65
Eric Snowc11183c2019-03-15 16:35:46 -060066static PyObject *
67interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
68{
69 static char *kwlist[] = {"id", "force", NULL};
Miss Islington (bot)ca14f042019-09-25 08:56:05 -070070 int64_t id;
Eric Snowc11183c2019-03-15 16:35:46 -060071 int force = 0;
72 if (!PyArg_ParseTupleAndKeywords(args, kwds,
Miss Islington (bot)ca14f042019-09-25 08:56:05 -070073 "O&|$p:InterpreterID.__init__", kwlist,
74 interp_id_converter, &id, &force)) {
Eric Snowc11183c2019-03-15 16:35:46 -060075 return NULL;
76 }
77
Eric Snowc11183c2019-03-15 16:35:46 -060078 return (PyObject *)newinterpid(cls, id, force);
79}
80
81static void
82interpid_dealloc(PyObject *v)
83{
84 int64_t id = ((interpid *)v)->id;
85 PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
86 if (interp != NULL) {
87 _PyInterpreterState_IDDecref(interp);
88 }
89 else {
90 // already deleted
91 PyErr_Clear();
92 }
93 Py_TYPE(v)->tp_free(v);
94}
95
96static PyObject *
97interpid_repr(PyObject *self)
98{
99 PyTypeObject *type = Py_TYPE(self);
100 const char *name = _PyType_Name(type);
101 interpid *id = (interpid *)self;
102 return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
103}
104
105static PyObject *
106interpid_str(PyObject *self)
107{
108 interpid *id = (interpid *)self;
109 return PyUnicode_FromFormat("%" PRId64 "", id->id);
110}
111
112static PyObject *
113interpid_int(PyObject *self)
114{
115 interpid *id = (interpid *)self;
116 return PyLong_FromLongLong(id->id);
117}
118
119static PyNumberMethods interpid_as_number = {
120 0, /* nb_add */
121 0, /* nb_subtract */
122 0, /* nb_multiply */
123 0, /* nb_remainder */
124 0, /* nb_divmod */
125 0, /* nb_power */
126 0, /* nb_negative */
127 0, /* nb_positive */
128 0, /* nb_absolute */
129 0, /* nb_bool */
130 0, /* nb_invert */
131 0, /* nb_lshift */
132 0, /* nb_rshift */
133 0, /* nb_and */
134 0, /* nb_xor */
135 0, /* nb_or */
136 (unaryfunc)interpid_int, /* nb_int */
137 0, /* nb_reserved */
138 0, /* nb_float */
139
140 0, /* nb_inplace_add */
141 0, /* nb_inplace_subtract */
142 0, /* nb_inplace_multiply */
143 0, /* nb_inplace_remainder */
144 0, /* nb_inplace_power */
145 0, /* nb_inplace_lshift */
146 0, /* nb_inplace_rshift */
147 0, /* nb_inplace_and */
148 0, /* nb_inplace_xor */
149 0, /* nb_inplace_or */
150
151 0, /* nb_floor_divide */
152 0, /* nb_true_divide */
153 0, /* nb_inplace_floor_divide */
154 0, /* nb_inplace_true_divide */
155
156 (unaryfunc)interpid_int, /* nb_index */
157};
158
159static Py_hash_t
160interpid_hash(PyObject *self)
161{
162 interpid *id = (interpid *)self;
163 PyObject *obj = PyLong_FromLongLong(id->id);
164 if (obj == NULL) {
165 return -1;
166 }
167 Py_hash_t hash = PyObject_Hash(obj);
168 Py_DECREF(obj);
169 return hash;
170}
171
172static PyObject *
173interpid_richcompare(PyObject *self, PyObject *other, int op)
174{
175 if (op != Py_EQ && op != Py_NE) {
176 Py_RETURN_NOTIMPLEMENTED;
177 }
178
179 if (!PyObject_TypeCheck(self, &_PyInterpreterID_Type)) {
180 Py_RETURN_NOTIMPLEMENTED;
181 }
182
183 interpid *id = (interpid *)self;
184 int equal;
185 if (PyObject_TypeCheck(other, &_PyInterpreterID_Type)) {
186 interpid *otherid = (interpid *)other;
187 equal = (id->id == otherid->id);
188 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300189 else if (PyLong_CheckExact(other)) {
190 /* Fast path */
191 int overflow;
192 long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
193 if (otherid == -1 && PyErr_Occurred()) {
Eric Snowc11183c2019-03-15 16:35:46 -0600194 return NULL;
195 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300196 equal = !overflow && (otherid >= 0) && (id->id == otherid);
197 }
198 else if (PyNumber_Check(other)) {
199 PyObject *pyid = PyLong_FromLongLong(id->id);
200 if (pyid == NULL) {
201 return NULL;
Eric Snowc11183c2019-03-15 16:35:46 -0600202 }
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300203 PyObject *res = PyObject_RichCompare(pyid, other, op);
204 Py_DECREF(pyid);
205 return res;
206 }
207 else {
208 Py_RETURN_NOTIMPLEMENTED;
Eric Snowc11183c2019-03-15 16:35:46 -0600209 }
210
211 if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
212 Py_RETURN_TRUE;
213 }
214 Py_RETURN_FALSE;
215}
216
217PyDoc_STRVAR(interpid_doc,
218"A interpreter ID identifies a interpreter and may be used as an int.");
219
220PyTypeObject _PyInterpreterID_Type = {
221 PyVarObject_HEAD_INIT(&PyType_Type, 0)
222 "InterpreterID", /* tp_name */
223 sizeof(interpid), /* tp_basicsize */
224 0, /* tp_itemsize */
225 (destructor)interpid_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200226 0, /* tp_vectorcall_offset */
Eric Snowc11183c2019-03-15 16:35:46 -0600227 0, /* tp_getattr */
228 0, /* tp_setattr */
229 0, /* tp_as_async */
230 (reprfunc)interpid_repr, /* tp_repr */
231 &interpid_as_number, /* tp_as_number */
232 0, /* tp_as_sequence */
233 0, /* tp_as_mapping */
234 interpid_hash, /* tp_hash */
235 0, /* tp_call */
236 (reprfunc)interpid_str, /* tp_str */
237 0, /* tp_getattro */
238 0, /* tp_setattro */
239 0, /* tp_as_buffer */
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300240 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
Eric Snowc11183c2019-03-15 16:35:46 -0600241 interpid_doc, /* tp_doc */
242 0, /* tp_traverse */
243 0, /* tp_clear */
244 interpid_richcompare, /* tp_richcompare */
245 0, /* tp_weaklistoffset */
246 0, /* tp_iter */
247 0, /* tp_iternext */
248 0, /* tp_methods */
249 0, /* tp_members */
250 0, /* tp_getset */
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300251 0, /* tp_base */
Eric Snowc11183c2019-03-15 16:35:46 -0600252 0, /* tp_dict */
253 0, /* tp_descr_get */
254 0, /* tp_descr_set */
255 0, /* tp_dictoffset */
256 0, /* tp_init */
257 0, /* tp_alloc */
258 interpid_new, /* tp_new */
259};
260
261PyObject *_PyInterpreterID_New(int64_t id)
262{
263 return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
264}
265
266PyObject *
267_PyInterpreterState_GetIDObject(PyInterpreterState *interp)
268{
269 if (_PyInterpreterState_IDInitref(interp) != 0) {
270 return NULL;
271 };
272 PY_INT64_T id = PyInterpreterState_GetID(interp);
273 if (id < 0) {
274 return NULL;
275 }
276 return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
277}
278
279PyInterpreterState *
280_PyInterpreterID_LookUp(PyObject *requested_id)
281{
282 int64_t id;
Miss Islington (bot)ca14f042019-09-25 08:56:05 -0700283 if (!interp_id_converter(requested_id, &id)) {
Serhiy Storchakaf37a9832019-09-14 19:36:19 +0300284 return NULL;
285 }
Eric Snowc11183c2019-03-15 16:35:46 -0600286 return _PyInterpreterState_LookUpID(id);
287}