interpreteridobject.c 8.7 KB

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