(root)/
Python-3.12.0/
Modules/
_weakref.c
       1  #include "Python.h"
       2  #include "pycore_object.h"   // _PyObject_GET_WEAKREFS_LISTPTR
       3  
       4  
       5  #define GET_WEAKREFS_LISTPTR(o) \
       6          ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o))
       7  
       8  /*[clinic input]
       9  module _weakref
      10  [clinic start generated code]*/
      11  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/
      12  
      13  #include "clinic/_weakref.c.h"
      14  
      15  /*[clinic input]
      16  
      17  _weakref.getweakrefcount -> Py_ssize_t
      18  
      19    object: object
      20    /
      21  
      22  Return the number of weak references to 'object'.
      23  [clinic start generated code]*/
      24  
      25  static Py_ssize_t
      26  _weakref_getweakrefcount_impl(PyObject *module, PyObject *object)
      27  /*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/
      28  {
      29      PyWeakReference **list;
      30  
      31      if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)))
      32          return 0;
      33  
      34      list = GET_WEAKREFS_LISTPTR(object);
      35      return _PyWeakref_GetWeakrefCount(*list);
      36  }
      37  
      38  
      39  static int
      40  is_dead_weakref(PyObject *value)
      41  {
      42      if (!PyWeakref_Check(value)) {
      43          PyErr_SetString(PyExc_TypeError, "not a weakref");
      44          return -1;
      45      }
      46      return PyWeakref_GET_OBJECT(value) == Py_None;
      47  }
      48  
      49  /*[clinic input]
      50  
      51  _weakref._remove_dead_weakref -> object
      52  
      53    dct: object(subclass_of='&PyDict_Type')
      54    key: object
      55    /
      56  
      57  Atomically remove key from dict if it points to a dead weakref.
      58  [clinic start generated code]*/
      59  
      60  static PyObject *
      61  _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct,
      62                                     PyObject *key)
      63  /*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/
      64  {
      65      if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) {
      66          if (PyErr_ExceptionMatches(PyExc_KeyError))
      67              /* This function is meant to allow safe weak-value dicts
      68                 with GC in another thread (see issue #28427), so it's
      69                 ok if the key doesn't exist anymore.
      70                 */
      71              PyErr_Clear();
      72          else
      73              return NULL;
      74      }
      75      Py_RETURN_NONE;
      76  }
      77  
      78  
      79  /*[clinic input]
      80  _weakref.getweakrefs
      81      object: object
      82      /
      83  
      84  Return a list of all weak reference objects pointing to 'object'.
      85  [clinic start generated code]*/
      86  
      87  static PyObject *
      88  _weakref_getweakrefs(PyObject *module, PyObject *object)
      89  /*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/
      90  {
      91      PyObject *result = NULL;
      92  
      93      if (_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
      94          PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
      95          Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
      96  
      97          result = PyList_New(count);
      98          if (result != NULL) {
      99              PyWeakReference *current = *list;
     100              Py_ssize_t i;
     101              for (i = 0; i < count; ++i) {
     102                  PyList_SET_ITEM(result, i, (PyObject *) current);
     103                  Py_INCREF(current);
     104                  current = current->wr_next;
     105              }
     106          }
     107      }
     108      else {
     109          result = PyList_New(0);
     110      }
     111      return result;
     112  }
     113  
     114  
     115  /*[clinic input]
     116  
     117  _weakref.proxy
     118      object: object
     119      callback: object(c_default="NULL") = None
     120      /
     121  
     122  Create a proxy object that weakly references 'object'.
     123  
     124  'callback', if given, is called with a reference to the
     125  proxy when 'object' is about to be finalized.
     126  [clinic start generated code]*/
     127  
     128  static PyObject *
     129  _weakref_proxy_impl(PyObject *module, PyObject *object, PyObject *callback)
     130  /*[clinic end generated code: output=d68fa4ad9ea40519 input=4808adf22fd137e7]*/
     131  {
     132      return PyWeakref_NewProxy(object, callback);
     133  }
     134  
     135  
     136  static PyMethodDef
     137  weakref_functions[] =  {
     138      _WEAKREF_GETWEAKREFCOUNT_METHODDEF
     139      _WEAKREF__REMOVE_DEAD_WEAKREF_METHODDEF
     140      _WEAKREF_GETWEAKREFS_METHODDEF
     141      _WEAKREF_PROXY_METHODDEF
     142      {NULL, NULL, 0, NULL}
     143  };
     144  
     145  static int
     146  weakref_exec(PyObject *module)
     147  {
     148      Py_INCREF(&_PyWeakref_RefType);
     149      if (PyModule_AddObject(module, "ref", (PyObject *) &_PyWeakref_RefType) < 0) {
     150          Py_DECREF(&_PyWeakref_RefType);
     151          return -1;
     152      }
     153      Py_INCREF(&_PyWeakref_RefType);
     154      if (PyModule_AddObject(module, "ReferenceType",
     155                             (PyObject *) &_PyWeakref_RefType) < 0) {
     156          Py_DECREF(&_PyWeakref_RefType);
     157          return -1;
     158      }
     159      Py_INCREF(&_PyWeakref_ProxyType);
     160      if (PyModule_AddObject(module, "ProxyType",
     161                             (PyObject *) &_PyWeakref_ProxyType) < 0) {
     162          Py_DECREF(&_PyWeakref_ProxyType);
     163          return -1;
     164      }
     165      Py_INCREF(&_PyWeakref_CallableProxyType);
     166      if (PyModule_AddObject(module, "CallableProxyType",
     167                             (PyObject *) &_PyWeakref_CallableProxyType) < 0) {
     168          Py_DECREF(&_PyWeakref_CallableProxyType);
     169          return -1;
     170      }
     171  
     172      return 0;
     173  }
     174  
     175  static struct PyModuleDef_Slot weakref_slots[] = {
     176      {Py_mod_exec, weakref_exec},
     177      {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
     178      {0, NULL}
     179  };
     180  
     181  static struct PyModuleDef weakrefmodule = {
     182      PyModuleDef_HEAD_INIT,
     183      "_weakref",
     184      "Weak-reference support module.",
     185      0,
     186      weakref_functions,
     187      weakref_slots,
     188      NULL,
     189      NULL,
     190      NULL
     191  };
     192  
     193  PyMODINIT_FUNC
     194  PyInit__weakref(void)
     195  {
     196      return PyModuleDef_Init(&weakrefmodule);
     197  }