weakrefobject.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. #include "Python.h"
  2. #include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR()
  3. #include "structmember.h" // PyMemberDef
  4. #define GET_WEAKREFS_LISTPTR(o) \
  5. ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o))
  6. Py_ssize_t
  7. _PyWeakref_GetWeakrefCount(PyWeakReference *head)
  8. {
  9. Py_ssize_t count = 0;
  10. while (head != NULL) {
  11. ++count;
  12. head = head->wr_next;
  13. }
  14. return count;
  15. }
  16. static PyObject *weakref_vectorcall(PyWeakReference *self, PyObject *const *args, size_t nargsf, PyObject *kwnames);
  17. static void
  18. init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
  19. {
  20. self->hash = -1;
  21. self->wr_object = ob;
  22. self->wr_prev = NULL;
  23. self->wr_next = NULL;
  24. self->wr_callback = Py_XNewRef(callback);
  25. self->vectorcall = (vectorcallfunc)weakref_vectorcall;
  26. }
  27. static PyWeakReference *
  28. new_weakref(PyObject *ob, PyObject *callback)
  29. {
  30. PyWeakReference *result;
  31. result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
  32. if (result) {
  33. init_weakref(result, ob, callback);
  34. PyObject_GC_Track(result);
  35. }
  36. return result;
  37. }
  38. /* This function clears the passed-in reference and removes it from the
  39. * list of weak references for the referent. This is the only code that
  40. * removes an item from the doubly-linked list of weak references for an
  41. * object; it is also responsible for clearing the callback slot.
  42. */
  43. static void
  44. clear_weakref(PyWeakReference *self)
  45. {
  46. PyObject *callback = self->wr_callback;
  47. if (self->wr_object != Py_None) {
  48. PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
  49. if (*list == self)
  50. /* If 'self' is the end of the list (and thus self->wr_next == NULL)
  51. then the weakref list itself (and thus the value of *list) will
  52. end up being set to NULL. */
  53. *list = self->wr_next;
  54. self->wr_object = Py_None;
  55. if (self->wr_prev != NULL)
  56. self->wr_prev->wr_next = self->wr_next;
  57. if (self->wr_next != NULL)
  58. self->wr_next->wr_prev = self->wr_prev;
  59. self->wr_prev = NULL;
  60. self->wr_next = NULL;
  61. }
  62. if (callback != NULL) {
  63. Py_DECREF(callback);
  64. self->wr_callback = NULL;
  65. }
  66. }
  67. /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
  68. * the callback intact and uncalled. It must be possible to call self's
  69. * tp_dealloc() after calling this, so self has to be left in a sane enough
  70. * state for that to work. We expect tp_dealloc to decref the callback
  71. * then. The reason for not letting clear_weakref() decref the callback
  72. * right now is that if the callback goes away, that may in turn trigger
  73. * another callback (if a weak reference to the callback exists) -- running
  74. * arbitrary Python code in the middle of gc is a disaster. The convolution
  75. * here allows gc to delay triggering such callbacks until the world is in
  76. * a sane state again.
  77. */
  78. void
  79. _PyWeakref_ClearRef(PyWeakReference *self)
  80. {
  81. PyObject *callback;
  82. assert(self != NULL);
  83. assert(PyWeakref_Check(self));
  84. /* Preserve and restore the callback around clear_weakref. */
  85. callback = self->wr_callback;
  86. self->wr_callback = NULL;
  87. clear_weakref(self);
  88. self->wr_callback = callback;
  89. }
  90. static void
  91. weakref_dealloc(PyObject *self)
  92. {
  93. PyObject_GC_UnTrack(self);
  94. clear_weakref((PyWeakReference *) self);
  95. Py_TYPE(self)->tp_free(self);
  96. }
  97. static int
  98. gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
  99. {
  100. Py_VISIT(self->wr_callback);
  101. return 0;
  102. }
  103. static int
  104. gc_clear(PyWeakReference *self)
  105. {
  106. clear_weakref(self);
  107. return 0;
  108. }
  109. static PyObject *
  110. weakref_vectorcall(PyWeakReference *self, PyObject *const *args,
  111. size_t nargsf, PyObject *kwnames)
  112. {
  113. if (!_PyArg_NoKwnames("weakref", kwnames)) {
  114. return NULL;
  115. }
  116. Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
  117. if (!_PyArg_CheckPositional("weakref", nargs, 0, 0)) {
  118. return NULL;
  119. }
  120. return Py_NewRef(PyWeakref_GET_OBJECT(self));
  121. }
  122. static Py_hash_t
  123. weakref_hash(PyWeakReference *self)
  124. {
  125. if (self->hash != -1)
  126. return self->hash;
  127. PyObject* obj = PyWeakref_GET_OBJECT(self);
  128. if (obj == Py_None) {
  129. PyErr_SetString(PyExc_TypeError, "weak object has gone away");
  130. return -1;
  131. }
  132. Py_INCREF(obj);
  133. self->hash = PyObject_Hash(obj);
  134. Py_DECREF(obj);
  135. return self->hash;
  136. }
  137. static PyObject *
  138. weakref_repr(PyWeakReference *self)
  139. {
  140. PyObject *name, *repr;
  141. PyObject* obj = PyWeakref_GET_OBJECT(self);
  142. if (obj == Py_None) {
  143. return PyUnicode_FromFormat("<weakref at %p; dead>", self);
  144. }
  145. Py_INCREF(obj);
  146. name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__));
  147. if (name == NULL || !PyUnicode_Check(name)) {
  148. repr = PyUnicode_FromFormat(
  149. "<weakref at %p; to '%s' at %p>",
  150. self,
  151. Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
  152. obj);
  153. }
  154. else {
  155. repr = PyUnicode_FromFormat(
  156. "<weakref at %p; to '%s' at %p (%U)>",
  157. self,
  158. Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
  159. obj,
  160. name);
  161. }
  162. Py_DECREF(obj);
  163. Py_XDECREF(name);
  164. return repr;
  165. }
  166. /* Weak references only support equality, not ordering. Two weak references
  167. are equal if the underlying objects are equal. If the underlying object has
  168. gone away, they are equal if they are identical. */
  169. static PyObject *
  170. weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
  171. {
  172. if ((op != Py_EQ && op != Py_NE) ||
  173. !PyWeakref_Check(self) ||
  174. !PyWeakref_Check(other)) {
  175. Py_RETURN_NOTIMPLEMENTED;
  176. }
  177. if (PyWeakref_GET_OBJECT(self) == Py_None
  178. || PyWeakref_GET_OBJECT(other) == Py_None) {
  179. int res = (self == other);
  180. if (op == Py_NE)
  181. res = !res;
  182. if (res)
  183. Py_RETURN_TRUE;
  184. else
  185. Py_RETURN_FALSE;
  186. }
  187. PyObject* obj = PyWeakref_GET_OBJECT(self);
  188. PyObject* other_obj = PyWeakref_GET_OBJECT(other);
  189. Py_INCREF(obj);
  190. Py_INCREF(other_obj);
  191. PyObject* res = PyObject_RichCompare(obj, other_obj, op);
  192. Py_DECREF(obj);
  193. Py_DECREF(other_obj);
  194. return res;
  195. }
  196. /* Given the head of an object's list of weak references, extract the
  197. * two callback-less refs (ref and proxy). Used to determine if the
  198. * shared references exist and to determine the back link for newly
  199. * inserted references.
  200. */
  201. static void
  202. get_basic_refs(PyWeakReference *head,
  203. PyWeakReference **refp, PyWeakReference **proxyp)
  204. {
  205. *refp = NULL;
  206. *proxyp = NULL;
  207. if (head != NULL && head->wr_callback == NULL) {
  208. /* We need to be careful that the "basic refs" aren't
  209. subclasses of the main types. That complicates this a
  210. little. */
  211. if (PyWeakref_CheckRefExact(head)) {
  212. *refp = head;
  213. head = head->wr_next;
  214. }
  215. if (head != NULL
  216. && head->wr_callback == NULL
  217. && PyWeakref_CheckProxy(head)) {
  218. *proxyp = head;
  219. /* head = head->wr_next; */
  220. }
  221. }
  222. }
  223. /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
  224. static void
  225. insert_after(PyWeakReference *newref, PyWeakReference *prev)
  226. {
  227. newref->wr_prev = prev;
  228. newref->wr_next = prev->wr_next;
  229. if (prev->wr_next != NULL)
  230. prev->wr_next->wr_prev = newref;
  231. prev->wr_next = newref;
  232. }
  233. /* Insert 'newref' at the head of the list; 'list' points to the variable
  234. * that stores the head.
  235. */
  236. static void
  237. insert_head(PyWeakReference *newref, PyWeakReference **list)
  238. {
  239. PyWeakReference *next = *list;
  240. newref->wr_prev = NULL;
  241. newref->wr_next = next;
  242. if (next != NULL)
  243. next->wr_prev = newref;
  244. *list = newref;
  245. }
  246. static int
  247. parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
  248. PyObject **obp, PyObject **callbackp)
  249. {
  250. return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
  251. }
  252. static PyObject *
  253. weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
  254. {
  255. PyWeakReference *self = NULL;
  256. PyObject *ob, *callback = NULL;
  257. if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
  258. PyWeakReference *ref, *proxy;
  259. PyWeakReference **list;
  260. if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
  261. PyErr_Format(PyExc_TypeError,
  262. "cannot create weak reference to '%s' object",
  263. Py_TYPE(ob)->tp_name);
  264. return NULL;
  265. }
  266. if (callback == Py_None)
  267. callback = NULL;
  268. list = GET_WEAKREFS_LISTPTR(ob);
  269. get_basic_refs(*list, &ref, &proxy);
  270. if (callback == NULL && type == &_PyWeakref_RefType) {
  271. if (ref != NULL) {
  272. /* We can re-use an existing reference. */
  273. return Py_NewRef(ref);
  274. }
  275. }
  276. /* We have to create a new reference. */
  277. /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
  278. list on ob can be mutated. This means that the ref and
  279. proxy pointers we got back earlier may have been collected,
  280. so we need to compute these values again before we use
  281. them. */
  282. self = (PyWeakReference *) (type->tp_alloc(type, 0));
  283. if (self != NULL) {
  284. init_weakref(self, ob, callback);
  285. if (callback == NULL && type == &_PyWeakref_RefType) {
  286. insert_head(self, list);
  287. }
  288. else {
  289. PyWeakReference *prev;
  290. get_basic_refs(*list, &ref, &proxy);
  291. prev = (proxy == NULL) ? ref : proxy;
  292. if (prev == NULL)
  293. insert_head(self, list);
  294. else
  295. insert_after(self, prev);
  296. }
  297. }
  298. }
  299. return (PyObject *)self;
  300. }
  301. static int
  302. weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
  303. {
  304. PyObject *tmp;
  305. if (!_PyArg_NoKeywords("ref", kwargs))
  306. return -1;
  307. if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
  308. return 0;
  309. else
  310. return -1;
  311. }
  312. static PyMemberDef weakref_members[] = {
  313. {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
  314. {NULL} /* Sentinel */
  315. };
  316. static PyMethodDef weakref_methods[] = {
  317. {"__class_getitem__", Py_GenericAlias,
  318. METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
  319. {NULL} /* Sentinel */
  320. };
  321. PyTypeObject
  322. _PyWeakref_RefType = {
  323. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  324. .tp_name = "weakref.ReferenceType",
  325. .tp_basicsize = sizeof(PyWeakReference),
  326. .tp_dealloc = weakref_dealloc,
  327. .tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
  328. .tp_call = PyVectorcall_Call,
  329. .tp_repr = (reprfunc)weakref_repr,
  330. .tp_hash = (hashfunc)weakref_hash,
  331. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
  332. Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE,
  333. .tp_traverse = (traverseproc)gc_traverse,
  334. .tp_clear = (inquiry)gc_clear,
  335. .tp_richcompare = (richcmpfunc)weakref_richcompare,
  336. .tp_methods = weakref_methods,
  337. .tp_members = weakref_members,
  338. .tp_init = weakref___init__,
  339. .tp_alloc = PyType_GenericAlloc,
  340. .tp_new = weakref___new__,
  341. .tp_free = PyObject_GC_Del,
  342. };
  343. static int
  344. proxy_checkref(PyWeakReference *proxy)
  345. {
  346. if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
  347. PyErr_SetString(PyExc_ReferenceError,
  348. "weakly-referenced object no longer exists");
  349. return 0;
  350. }
  351. return 1;
  352. }
  353. /* If a parameter is a proxy, check that it is still "live" and wrap it,
  354. * replacing the original value with the raw object. Raises ReferenceError
  355. * if the param is a dead proxy.
  356. */
  357. #define UNWRAP(o) \
  358. if (PyWeakref_CheckProxy(o)) { \
  359. if (!proxy_checkref((PyWeakReference *)o)) \
  360. return NULL; \
  361. o = PyWeakref_GET_OBJECT(o); \
  362. }
  363. #define WRAP_UNARY(method, generic) \
  364. static PyObject * \
  365. method(PyObject *proxy) { \
  366. UNWRAP(proxy); \
  367. Py_INCREF(proxy); \
  368. PyObject* res = generic(proxy); \
  369. Py_DECREF(proxy); \
  370. return res; \
  371. }
  372. #define WRAP_BINARY(method, generic) \
  373. static PyObject * \
  374. method(PyObject *x, PyObject *y) { \
  375. UNWRAP(x); \
  376. UNWRAP(y); \
  377. Py_INCREF(x); \
  378. Py_INCREF(y); \
  379. PyObject* res = generic(x, y); \
  380. Py_DECREF(x); \
  381. Py_DECREF(y); \
  382. return res; \
  383. }
  384. /* Note that the third arg needs to be checked for NULL since the tp_call
  385. * slot can receive NULL for this arg.
  386. */
  387. #define WRAP_TERNARY(method, generic) \
  388. static PyObject * \
  389. method(PyObject *proxy, PyObject *v, PyObject *w) { \
  390. UNWRAP(proxy); \
  391. UNWRAP(v); \
  392. if (w != NULL) \
  393. UNWRAP(w); \
  394. Py_INCREF(proxy); \
  395. Py_INCREF(v); \
  396. Py_XINCREF(w); \
  397. PyObject* res = generic(proxy, v, w); \
  398. Py_DECREF(proxy); \
  399. Py_DECREF(v); \
  400. Py_XDECREF(w); \
  401. return res; \
  402. }
  403. #define WRAP_METHOD(method, SPECIAL) \
  404. static PyObject * \
  405. method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
  406. UNWRAP(proxy); \
  407. Py_INCREF(proxy); \
  408. PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
  409. Py_DECREF(proxy); \
  410. return res; \
  411. }
  412. /* direct slots */
  413. WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
  414. WRAP_UNARY(proxy_str, PyObject_Str)
  415. WRAP_TERNARY(proxy_call, PyObject_Call)
  416. static PyObject *
  417. proxy_repr(PyWeakReference *proxy)
  418. {
  419. return PyUnicode_FromFormat(
  420. "<weakproxy at %p to %s at %p>",
  421. proxy,
  422. Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
  423. PyWeakref_GET_OBJECT(proxy));
  424. }
  425. static int
  426. proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
  427. {
  428. if (!proxy_checkref(proxy))
  429. return -1;
  430. PyObject *obj = PyWeakref_GET_OBJECT(proxy);
  431. Py_INCREF(obj);
  432. int res = PyObject_SetAttr(obj, name, value);
  433. Py_DECREF(obj);
  434. return res;
  435. }
  436. static PyObject *
  437. proxy_richcompare(PyObject *proxy, PyObject *v, int op)
  438. {
  439. UNWRAP(proxy);
  440. UNWRAP(v);
  441. return PyObject_RichCompare(proxy, v, op);
  442. }
  443. /* number slots */
  444. WRAP_BINARY(proxy_add, PyNumber_Add)
  445. WRAP_BINARY(proxy_sub, PyNumber_Subtract)
  446. WRAP_BINARY(proxy_mul, PyNumber_Multiply)
  447. WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
  448. WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
  449. WRAP_BINARY(proxy_mod, PyNumber_Remainder)
  450. WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
  451. WRAP_TERNARY(proxy_pow, PyNumber_Power)
  452. WRAP_UNARY(proxy_neg, PyNumber_Negative)
  453. WRAP_UNARY(proxy_pos, PyNumber_Positive)
  454. WRAP_UNARY(proxy_abs, PyNumber_Absolute)
  455. WRAP_UNARY(proxy_invert, PyNumber_Invert)
  456. WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
  457. WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
  458. WRAP_BINARY(proxy_and, PyNumber_And)
  459. WRAP_BINARY(proxy_xor, PyNumber_Xor)
  460. WRAP_BINARY(proxy_or, PyNumber_Or)
  461. WRAP_UNARY(proxy_int, PyNumber_Long)
  462. WRAP_UNARY(proxy_float, PyNumber_Float)
  463. WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
  464. WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
  465. WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
  466. WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
  467. WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
  468. WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
  469. WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
  470. WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
  471. WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
  472. WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
  473. WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
  474. WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
  475. WRAP_UNARY(proxy_index, PyNumber_Index)
  476. WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
  477. WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
  478. static int
  479. proxy_bool(PyWeakReference *proxy)
  480. {
  481. PyObject *o = PyWeakref_GET_OBJECT(proxy);
  482. if (!proxy_checkref(proxy)) {
  483. return -1;
  484. }
  485. Py_INCREF(o);
  486. int res = PyObject_IsTrue(o);
  487. Py_DECREF(o);
  488. return res;
  489. }
  490. static void
  491. proxy_dealloc(PyWeakReference *self)
  492. {
  493. PyObject_GC_UnTrack(self);
  494. if (self->wr_callback != NULL)
  495. PyObject_GC_UnTrack((PyObject *)self);
  496. clear_weakref(self);
  497. PyObject_GC_Del(self);
  498. }
  499. /* sequence slots */
  500. static int
  501. proxy_contains(PyWeakReference *proxy, PyObject *value)
  502. {
  503. if (!proxy_checkref(proxy))
  504. return -1;
  505. PyObject *obj = PyWeakref_GET_OBJECT(proxy);
  506. Py_INCREF(obj);
  507. int res = PySequence_Contains(obj, value);
  508. Py_DECREF(obj);
  509. return res;
  510. }
  511. /* mapping slots */
  512. static Py_ssize_t
  513. proxy_length(PyWeakReference *proxy)
  514. {
  515. if (!proxy_checkref(proxy))
  516. return -1;
  517. PyObject *obj = PyWeakref_GET_OBJECT(proxy);
  518. Py_INCREF(obj);
  519. Py_ssize_t res = PyObject_Length(obj);
  520. Py_DECREF(obj);
  521. return res;
  522. }
  523. WRAP_BINARY(proxy_getitem, PyObject_GetItem)
  524. static int
  525. proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
  526. {
  527. if (!proxy_checkref(proxy))
  528. return -1;
  529. PyObject *obj = PyWeakref_GET_OBJECT(proxy);
  530. Py_INCREF(obj);
  531. int res;
  532. if (value == NULL) {
  533. res = PyObject_DelItem(obj, key);
  534. } else {
  535. res = PyObject_SetItem(obj, key, value);
  536. }
  537. Py_DECREF(obj);
  538. return res;
  539. }
  540. /* iterator slots */
  541. static PyObject *
  542. proxy_iter(PyWeakReference *proxy)
  543. {
  544. if (!proxy_checkref(proxy))
  545. return NULL;
  546. PyObject *obj = PyWeakref_GET_OBJECT(proxy);
  547. Py_INCREF(obj);
  548. PyObject* res = PyObject_GetIter(obj);
  549. Py_DECREF(obj);
  550. return res;
  551. }
  552. static PyObject *
  553. proxy_iternext(PyWeakReference *proxy)
  554. {
  555. if (!proxy_checkref(proxy))
  556. return NULL;
  557. PyObject *obj = PyWeakref_GET_OBJECT(proxy);
  558. if (!PyIter_Check(obj)) {
  559. PyErr_Format(PyExc_TypeError,
  560. "Weakref proxy referenced a non-iterator '%.200s' object",
  561. Py_TYPE(obj)->tp_name);
  562. return NULL;
  563. }
  564. Py_INCREF(obj);
  565. PyObject* res = PyIter_Next(obj);
  566. Py_DECREF(obj);
  567. return res;
  568. }
  569. WRAP_METHOD(proxy_bytes, __bytes__)
  570. WRAP_METHOD(proxy_reversed, __reversed__)
  571. static PyMethodDef proxy_methods[] = {
  572. {"__bytes__", proxy_bytes, METH_NOARGS},
  573. {"__reversed__", proxy_reversed, METH_NOARGS},
  574. {NULL, NULL}
  575. };
  576. static PyNumberMethods proxy_as_number = {
  577. proxy_add, /*nb_add*/
  578. proxy_sub, /*nb_subtract*/
  579. proxy_mul, /*nb_multiply*/
  580. proxy_mod, /*nb_remainder*/
  581. proxy_divmod, /*nb_divmod*/
  582. proxy_pow, /*nb_power*/
  583. proxy_neg, /*nb_negative*/
  584. proxy_pos, /*nb_positive*/
  585. proxy_abs, /*nb_absolute*/
  586. (inquiry)proxy_bool, /*nb_bool*/
  587. proxy_invert, /*nb_invert*/
  588. proxy_lshift, /*nb_lshift*/
  589. proxy_rshift, /*nb_rshift*/
  590. proxy_and, /*nb_and*/
  591. proxy_xor, /*nb_xor*/
  592. proxy_or, /*nb_or*/
  593. proxy_int, /*nb_int*/
  594. 0, /*nb_reserved*/
  595. proxy_float, /*nb_float*/
  596. proxy_iadd, /*nb_inplace_add*/
  597. proxy_isub, /*nb_inplace_subtract*/
  598. proxy_imul, /*nb_inplace_multiply*/
  599. proxy_imod, /*nb_inplace_remainder*/
  600. proxy_ipow, /*nb_inplace_power*/
  601. proxy_ilshift, /*nb_inplace_lshift*/
  602. proxy_irshift, /*nb_inplace_rshift*/
  603. proxy_iand, /*nb_inplace_and*/
  604. proxy_ixor, /*nb_inplace_xor*/
  605. proxy_ior, /*nb_inplace_or*/
  606. proxy_floor_div, /*nb_floor_divide*/
  607. proxy_true_div, /*nb_true_divide*/
  608. proxy_ifloor_div, /*nb_inplace_floor_divide*/
  609. proxy_itrue_div, /*nb_inplace_true_divide*/
  610. proxy_index, /*nb_index*/
  611. proxy_matmul, /*nb_matrix_multiply*/
  612. proxy_imatmul, /*nb_inplace_matrix_multiply*/
  613. };
  614. static PySequenceMethods proxy_as_sequence = {
  615. (lenfunc)proxy_length, /*sq_length*/
  616. 0, /*sq_concat*/
  617. 0, /*sq_repeat*/
  618. 0, /*sq_item*/
  619. 0, /*sq_slice*/
  620. 0, /*sq_ass_item*/
  621. 0, /*sq_ass_slice*/
  622. (objobjproc)proxy_contains, /* sq_contains */
  623. };
  624. static PyMappingMethods proxy_as_mapping = {
  625. (lenfunc)proxy_length, /*mp_length*/
  626. proxy_getitem, /*mp_subscript*/
  627. (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
  628. };
  629. PyTypeObject
  630. _PyWeakref_ProxyType = {
  631. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  632. "weakref.ProxyType",
  633. sizeof(PyWeakReference),
  634. 0,
  635. /* methods */
  636. (destructor)proxy_dealloc, /* tp_dealloc */
  637. 0, /* tp_vectorcall_offset */
  638. 0, /* tp_getattr */
  639. 0, /* tp_setattr */
  640. 0, /* tp_as_async */
  641. (reprfunc)proxy_repr, /* tp_repr */
  642. &proxy_as_number, /* tp_as_number */
  643. &proxy_as_sequence, /* tp_as_sequence */
  644. &proxy_as_mapping, /* tp_as_mapping */
  645. // Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies).
  646. 0, /* tp_hash */
  647. 0, /* tp_call */
  648. proxy_str, /* tp_str */
  649. proxy_getattr, /* tp_getattro */
  650. (setattrofunc)proxy_setattr, /* tp_setattro */
  651. 0, /* tp_as_buffer */
  652. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  653. 0, /* tp_doc */
  654. (traverseproc)gc_traverse, /* tp_traverse */
  655. (inquiry)gc_clear, /* tp_clear */
  656. proxy_richcompare, /* tp_richcompare */
  657. 0, /* tp_weaklistoffset */
  658. (getiterfunc)proxy_iter, /* tp_iter */
  659. (iternextfunc)proxy_iternext, /* tp_iternext */
  660. proxy_methods, /* tp_methods */
  661. };
  662. PyTypeObject
  663. _PyWeakref_CallableProxyType = {
  664. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  665. "weakref.CallableProxyType",
  666. sizeof(PyWeakReference),
  667. 0,
  668. /* methods */
  669. (destructor)proxy_dealloc, /* tp_dealloc */
  670. 0, /* tp_vectorcall_offset */
  671. 0, /* tp_getattr */
  672. 0, /* tp_setattr */
  673. 0, /* tp_as_async */
  674. (unaryfunc)proxy_repr, /* tp_repr */
  675. &proxy_as_number, /* tp_as_number */
  676. &proxy_as_sequence, /* tp_as_sequence */
  677. &proxy_as_mapping, /* tp_as_mapping */
  678. 0, /* tp_hash */
  679. proxy_call, /* tp_call */
  680. proxy_str, /* tp_str */
  681. proxy_getattr, /* tp_getattro */
  682. (setattrofunc)proxy_setattr, /* tp_setattro */
  683. 0, /* tp_as_buffer */
  684. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  685. 0, /* tp_doc */
  686. (traverseproc)gc_traverse, /* tp_traverse */
  687. (inquiry)gc_clear, /* tp_clear */
  688. proxy_richcompare, /* tp_richcompare */
  689. 0, /* tp_weaklistoffset */
  690. (getiterfunc)proxy_iter, /* tp_iter */
  691. (iternextfunc)proxy_iternext, /* tp_iternext */
  692. };
  693. PyObject *
  694. PyWeakref_NewRef(PyObject *ob, PyObject *callback)
  695. {
  696. PyWeakReference *result = NULL;
  697. PyWeakReference **list;
  698. PyWeakReference *ref, *proxy;
  699. if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
  700. PyErr_Format(PyExc_TypeError,
  701. "cannot create weak reference to '%s' object",
  702. Py_TYPE(ob)->tp_name);
  703. return NULL;
  704. }
  705. list = GET_WEAKREFS_LISTPTR(ob);
  706. get_basic_refs(*list, &ref, &proxy);
  707. if (callback == Py_None)
  708. callback = NULL;
  709. if (callback == NULL)
  710. /* return existing weak reference if it exists */
  711. result = ref;
  712. if (result != NULL)
  713. Py_INCREF(result);
  714. else {
  715. /* Note: new_weakref() can trigger cyclic GC, so the weakref
  716. list on ob can be mutated. This means that the ref and
  717. proxy pointers we got back earlier may have been collected,
  718. so we need to compute these values again before we use
  719. them. */
  720. result = new_weakref(ob, callback);
  721. if (result != NULL) {
  722. get_basic_refs(*list, &ref, &proxy);
  723. if (callback == NULL) {
  724. if (ref == NULL)
  725. insert_head(result, list);
  726. else {
  727. /* Someone else added a ref without a callback
  728. during GC. Return that one instead of this one
  729. to avoid violating the invariants of the list
  730. of weakrefs for ob. */
  731. Py_SETREF(result, (PyWeakReference*)Py_NewRef(ref));
  732. }
  733. }
  734. else {
  735. PyWeakReference *prev;
  736. prev = (proxy == NULL) ? ref : proxy;
  737. if (prev == NULL)
  738. insert_head(result, list);
  739. else
  740. insert_after(result, prev);
  741. }
  742. }
  743. }
  744. return (PyObject *) result;
  745. }
  746. PyObject *
  747. PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
  748. {
  749. PyWeakReference *result = NULL;
  750. PyWeakReference **list;
  751. PyWeakReference *ref, *proxy;
  752. if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
  753. PyErr_Format(PyExc_TypeError,
  754. "cannot create weak reference to '%s' object",
  755. Py_TYPE(ob)->tp_name);
  756. return NULL;
  757. }
  758. list = GET_WEAKREFS_LISTPTR(ob);
  759. get_basic_refs(*list, &ref, &proxy);
  760. if (callback == Py_None)
  761. callback = NULL;
  762. if (callback == NULL)
  763. /* attempt to return an existing weak reference if it exists */
  764. result = proxy;
  765. if (result != NULL)
  766. Py_INCREF(result);
  767. else {
  768. /* Note: new_weakref() can trigger cyclic GC, so the weakref
  769. list on ob can be mutated. This means that the ref and
  770. proxy pointers we got back earlier may have been collected,
  771. so we need to compute these values again before we use
  772. them. */
  773. result = new_weakref(ob, callback);
  774. if (result != NULL) {
  775. PyWeakReference *prev;
  776. if (PyCallable_Check(ob)) {
  777. Py_SET_TYPE(result, &_PyWeakref_CallableProxyType);
  778. }
  779. else {
  780. Py_SET_TYPE(result, &_PyWeakref_ProxyType);
  781. }
  782. get_basic_refs(*list, &ref, &proxy);
  783. if (callback == NULL) {
  784. if (proxy != NULL) {
  785. /* Someone else added a proxy without a callback
  786. during GC. Return that one instead of this one
  787. to avoid violating the invariants of the list
  788. of weakrefs for ob. */
  789. Py_SETREF(result, (PyWeakReference*)Py_NewRef(proxy));
  790. goto skip_insert;
  791. }
  792. prev = ref;
  793. }
  794. else
  795. prev = (proxy == NULL) ? ref : proxy;
  796. if (prev == NULL)
  797. insert_head(result, list);
  798. else
  799. insert_after(result, prev);
  800. skip_insert:
  801. ;
  802. }
  803. }
  804. return (PyObject *) result;
  805. }
  806. PyObject *
  807. PyWeakref_GetObject(PyObject *ref)
  808. {
  809. if (ref == NULL || !PyWeakref_Check(ref)) {
  810. PyErr_BadInternalCall();
  811. return NULL;
  812. }
  813. return PyWeakref_GET_OBJECT(ref);
  814. }
  815. /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
  816. * handle_weakrefs().
  817. */
  818. static void
  819. handle_callback(PyWeakReference *ref, PyObject *callback)
  820. {
  821. PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref);
  822. if (cbresult == NULL)
  823. PyErr_WriteUnraisable(callback);
  824. else
  825. Py_DECREF(cbresult);
  826. }
  827. /* This function is called by the tp_dealloc handler to clear weak references.
  828. *
  829. * This iterates through the weak references for 'object' and calls callbacks
  830. * for those references which have one. It returns when all callbacks have
  831. * been attempted.
  832. */
  833. void
  834. PyObject_ClearWeakRefs(PyObject *object)
  835. {
  836. PyWeakReference **list;
  837. if (object == NULL
  838. || !_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
  839. || Py_REFCNT(object) != 0)
  840. {
  841. PyErr_BadInternalCall();
  842. return;
  843. }
  844. list = GET_WEAKREFS_LISTPTR(object);
  845. /* Remove the callback-less basic and proxy references */
  846. if (*list != NULL && (*list)->wr_callback == NULL) {
  847. clear_weakref(*list);
  848. if (*list != NULL && (*list)->wr_callback == NULL)
  849. clear_weakref(*list);
  850. }
  851. if (*list != NULL) {
  852. PyWeakReference *current = *list;
  853. Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
  854. PyObject *exc = PyErr_GetRaisedException();
  855. if (count == 1) {
  856. PyObject *callback = current->wr_callback;
  857. current->wr_callback = NULL;
  858. clear_weakref(current);
  859. if (callback != NULL) {
  860. if (Py_REFCNT((PyObject *)current) > 0) {
  861. handle_callback(current, callback);
  862. }
  863. Py_DECREF(callback);
  864. }
  865. }
  866. else {
  867. PyObject *tuple;
  868. Py_ssize_t i = 0;
  869. tuple = PyTuple_New(count * 2);
  870. if (tuple == NULL) {
  871. _PyErr_ChainExceptions1(exc);
  872. return;
  873. }
  874. for (i = 0; i < count; ++i) {
  875. PyWeakReference *next = current->wr_next;
  876. if (Py_REFCNT((PyObject *)current) > 0) {
  877. PyTuple_SET_ITEM(tuple, i * 2, Py_NewRef(current));
  878. PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
  879. }
  880. else {
  881. Py_DECREF(current->wr_callback);
  882. }
  883. current->wr_callback = NULL;
  884. clear_weakref(current);
  885. current = next;
  886. }
  887. for (i = 0; i < count; ++i) {
  888. PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
  889. /* The tuple may have slots left to NULL */
  890. if (callback != NULL) {
  891. PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
  892. handle_callback((PyWeakReference *)item, callback);
  893. }
  894. }
  895. Py_DECREF(tuple);
  896. }
  897. assert(!PyErr_Occurred());
  898. PyErr_SetRaisedException(exc);
  899. }
  900. }
  901. /* This function is called by _PyStaticType_Dealloc() to clear weak references.
  902. *
  903. * This is called at the end of runtime finalization, so we can just
  904. * wipe out the type's weaklist. We don't bother with callbacks
  905. * or anything else.
  906. */
  907. void
  908. _PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
  909. {
  910. static_builtin_state *state = _PyStaticType_GetState(interp, type);
  911. PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state);
  912. while (*list != NULL) {
  913. /* Note that clear_weakref() pops the first ref off the type's
  914. weaklist before clearing its wr_object and wr_callback.
  915. That is how we're able to loop over the list. */
  916. clear_weakref((PyWeakReference *)*list);
  917. }
  918. }