mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 bbee57fa8c
			
		
	
	
		bbee57fa8c
		
			
		
	
	
	
	
		
			
			Mostly we unify the two different implementations of the conversion code (from PyObject * to int64_t. We also drop the PyArg_ParseTuple()-style converter function, as well as rename and move PyInterpreterID_LookUp().
		
			
				
	
	
		
			274 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			274 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* InterpreterID object */
 | |
| 
 | |
| #include "Python.h"
 | |
| #include "pycore_interp.h"        // _PyInterpreterState_LookUpID()
 | |
| #include "interpreteridobject.h"
 | |
| 
 | |
| 
 | |
| typedef struct interpid {
 | |
|     PyObject_HEAD
 | |
|     int64_t id;
 | |
| } interpid;
 | |
| 
 | |
| int64_t
 | |
| _PyInterpreterID_GetID(PyObject *self)
 | |
| {
 | |
|     if (!PyObject_TypeCheck(self, &PyInterpreterID_Type)) {
 | |
|         PyErr_Format(PyExc_TypeError,
 | |
|                      "expected an InterpreterID, got %R",
 | |
|                      self);
 | |
|         return -1;
 | |
| 
 | |
|     }
 | |
|     int64_t id = ((interpid *)self)->id;
 | |
|     assert(id >= 0);
 | |
|     return id;
 | |
| }
 | |
| 
 | |
| static interpid *
 | |
| newinterpid(PyTypeObject *cls, int64_t id, int force)
 | |
| {
 | |
|     PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
 | |
|     if (interp == NULL) {
 | |
|         if (force) {
 | |
|             PyErr_Clear();
 | |
|         }
 | |
|         else {
 | |
|             return NULL;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (interp != NULL) {
 | |
|         if (_PyInterpreterState_IDIncref(interp) < 0) {
 | |
|             return NULL;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     interpid *self = PyObject_New(interpid, cls);
 | |
|     if (self == NULL) {
 | |
|         if (interp != NULL) {
 | |
|             _PyInterpreterState_IDDecref(interp);
 | |
|         }
 | |
|         return NULL;
 | |
|     }
 | |
|     self->id = id;
 | |
| 
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
 | |
| {
 | |
|     static char *kwlist[] = {"id", "force", NULL};
 | |
|     PyObject *idobj;
 | |
|     int force = 0;
 | |
|     if (!PyArg_ParseTupleAndKeywords(args, kwds,
 | |
|                                      "O|$p:InterpreterID.__init__", kwlist,
 | |
|                                      &idobj, &force)) {
 | |
|         return NULL;
 | |
|     }
 | |
|     int64_t id = _PyInterpreterState_ObjectToID(idobj);
 | |
|     if (id < 0) {
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     return (PyObject *)newinterpid(cls, id, force);
 | |
| }
 | |
| 
 | |
| static void
 | |
| interpid_dealloc(PyObject *v)
 | |
| {
 | |
|     int64_t id = ((interpid *)v)->id;
 | |
|     PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
 | |
|     if (interp != NULL) {
 | |
|         _PyInterpreterState_IDDecref(interp);
 | |
|     }
 | |
|     else {
 | |
|         // already deleted
 | |
|         PyErr_Clear();
 | |
|     }
 | |
|     Py_TYPE(v)->tp_free(v);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| interpid_repr(PyObject *self)
 | |
| {
 | |
|     PyTypeObject *type = Py_TYPE(self);
 | |
|     const char *name = _PyType_Name(type);
 | |
|     interpid *id = (interpid *)self;
 | |
|     return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| interpid_str(PyObject *self)
 | |
| {
 | |
|     interpid *id = (interpid *)self;
 | |
|     return PyUnicode_FromFormat("%" PRId64 "", id->id);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| interpid_int(PyObject *self)
 | |
| {
 | |
|     interpid *id = (interpid *)self;
 | |
|     return PyLong_FromLongLong(id->id);
 | |
| }
 | |
| 
 | |
| static PyNumberMethods interpid_as_number = {
 | |
|      0,                       /* nb_add */
 | |
|      0,                       /* nb_subtract */
 | |
|      0,                       /* nb_multiply */
 | |
|      0,                       /* nb_remainder */
 | |
|      0,                       /* nb_divmod */
 | |
|      0,                       /* nb_power */
 | |
|      0,                       /* nb_negative */
 | |
|      0,                       /* nb_positive */
 | |
|      0,                       /* nb_absolute */
 | |
|      0,                       /* nb_bool */
 | |
|      0,                       /* nb_invert */
 | |
|      0,                       /* nb_lshift */
 | |
|      0,                       /* nb_rshift */
 | |
|      0,                       /* nb_and */
 | |
|      0,                       /* nb_xor */
 | |
|      0,                       /* nb_or */
 | |
|      (unaryfunc)interpid_int, /* nb_int */
 | |
|      0,                       /* nb_reserved */
 | |
|      0,                       /* nb_float */
 | |
| 
 | |
|      0,                       /* nb_inplace_add */
 | |
|      0,                       /* nb_inplace_subtract */
 | |
|      0,                       /* nb_inplace_multiply */
 | |
|      0,                       /* nb_inplace_remainder */
 | |
|      0,                       /* nb_inplace_power */
 | |
|      0,                       /* nb_inplace_lshift */
 | |
|      0,                       /* nb_inplace_rshift */
 | |
|      0,                       /* nb_inplace_and */
 | |
|      0,                       /* nb_inplace_xor */
 | |
|      0,                       /* nb_inplace_or */
 | |
| 
 | |
|      0,                       /* nb_floor_divide */
 | |
|      0,                       /* nb_true_divide */
 | |
|      0,                       /* nb_inplace_floor_divide */
 | |
|      0,                       /* nb_inplace_true_divide */
 | |
| 
 | |
|      (unaryfunc)interpid_int, /* nb_index */
 | |
| };
 | |
| 
 | |
| static Py_hash_t
 | |
| interpid_hash(PyObject *self)
 | |
| {
 | |
|     interpid *id = (interpid *)self;
 | |
|     PyObject *obj = PyLong_FromLongLong(id->id);
 | |
|     if (obj == NULL) {
 | |
|         return -1;
 | |
|     }
 | |
|     Py_hash_t hash = PyObject_Hash(obj);
 | |
|     Py_DECREF(obj);
 | |
|     return hash;
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| interpid_richcompare(PyObject *self, PyObject *other, int op)
 | |
| {
 | |
|     if (op != Py_EQ && op != Py_NE) {
 | |
|         Py_RETURN_NOTIMPLEMENTED;
 | |
|     }
 | |
| 
 | |
|     if (!PyObject_TypeCheck(self, &PyInterpreterID_Type)) {
 | |
|         Py_RETURN_NOTIMPLEMENTED;
 | |
|     }
 | |
| 
 | |
|     interpid *id = (interpid *)self;
 | |
|     int equal;
 | |
|     if (PyObject_TypeCheck(other, &PyInterpreterID_Type)) {
 | |
|         interpid *otherid = (interpid *)other;
 | |
|         equal = (id->id == otherid->id);
 | |
|     }
 | |
|     else if (PyLong_CheckExact(other)) {
 | |
|         /* Fast path */
 | |
|         int overflow;
 | |
|         long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
 | |
|         if (otherid == -1 && PyErr_Occurred()) {
 | |
|             return NULL;
 | |
|         }
 | |
|         equal = !overflow && (otherid >= 0) && (id->id == otherid);
 | |
|     }
 | |
|     else if (PyNumber_Check(other)) {
 | |
|         PyObject *pyid = PyLong_FromLongLong(id->id);
 | |
|         if (pyid == NULL) {
 | |
|             return NULL;
 | |
|         }
 | |
|         PyObject *res = PyObject_RichCompare(pyid, other, op);
 | |
|         Py_DECREF(pyid);
 | |
|         return res;
 | |
|     }
 | |
|     else {
 | |
|         Py_RETURN_NOTIMPLEMENTED;
 | |
|     }
 | |
| 
 | |
|     if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
 | |
|         Py_RETURN_TRUE;
 | |
|     }
 | |
|     Py_RETURN_FALSE;
 | |
| }
 | |
| 
 | |
| PyDoc_STRVAR(interpid_doc,
 | |
| "A interpreter ID identifies a interpreter and may be used as an int.");
 | |
| 
 | |
| PyTypeObject PyInterpreterID_Type = {
 | |
|     PyVarObject_HEAD_INIT(&PyType_Type, 0)
 | |
|     "InterpreterID",   /* tp_name */
 | |
|     sizeof(interpid),               /* tp_basicsize */
 | |
|     0,                              /* tp_itemsize */
 | |
|     (destructor)interpid_dealloc,   /* tp_dealloc */
 | |
|     0,                              /* tp_vectorcall_offset */
 | |
|     0,                              /* tp_getattr */
 | |
|     0,                              /* tp_setattr */
 | |
|     0,                              /* tp_as_async */
 | |
|     (reprfunc)interpid_repr,        /* tp_repr */
 | |
|     &interpid_as_number,            /* tp_as_number */
 | |
|     0,                              /* tp_as_sequence */
 | |
|     0,                              /* tp_as_mapping */
 | |
|     interpid_hash,                  /* tp_hash */
 | |
|     0,                              /* tp_call */
 | |
|     (reprfunc)interpid_str,         /* tp_str */
 | |
|     0,                              /* tp_getattro */
 | |
|     0,                              /* tp_setattro */
 | |
|     0,                              /* tp_as_buffer */
 | |
|     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
 | |
|     interpid_doc,                   /* tp_doc */
 | |
|     0,                              /* tp_traverse */
 | |
|     0,                              /* tp_clear */
 | |
|     interpid_richcompare,           /* tp_richcompare */
 | |
|     0,                              /* tp_weaklistoffset */
 | |
|     0,                              /* tp_iter */
 | |
|     0,                              /* tp_iternext */
 | |
|     0,                              /* tp_methods */
 | |
|     0,                              /* tp_members */
 | |
|     0,                              /* tp_getset */
 | |
|     0,                              /* tp_base */
 | |
|     0,                              /* tp_dict */
 | |
|     0,                              /* tp_descr_get */
 | |
|     0,                              /* tp_descr_set */
 | |
|     0,                              /* tp_dictoffset */
 | |
|     0,                              /* tp_init */
 | |
|     0,                              /* tp_alloc */
 | |
|     interpid_new,                   /* tp_new */
 | |
| };
 | |
| 
 | |
| PyObject *PyInterpreterID_New(int64_t id)
 | |
| {
 | |
|     return (PyObject *)newinterpid(&PyInterpreterID_Type, id, 0);
 | |
| }
 | |
| 
 | |
| PyObject *
 | |
| PyInterpreterState_GetIDObject(PyInterpreterState *interp)
 | |
| {
 | |
|     if (_PyInterpreterState_IDInitref(interp) != 0) {
 | |
|         return NULL;
 | |
|     };
 | |
|     int64_t id = PyInterpreterState_GetID(interp);
 | |
|     if (id < 0) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return (PyObject *)newinterpid(&PyInterpreterID_Type, id, 0);
 | |
| }
 |