-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Closed as not planned
Closed as not planned
Copy link
Description
According to Include/object.h
in Python's source code:
struct _object {
// ob_tid stores the thread id (or zero). It is also used by the GC and the
// trashcan mechanism as a linked list pointer and by the GC to store the
// computed "gc_refs" refcount.
uintptr_t ob_tid;
uint16_t ob_flags;
PyMutex ob_mutex; // per-object lock
uint8_t ob_gc_bits; // gc-related state
uint32_t ob_ref_local; // local reference count
Py_ssize_t ob_ref_shared; // shared (atomic) reference count
PyTypeObject *ob_type;
};
When I managed to use an external tool, pyobject (pip install pyobject
), to inspect them:
C:\Users\admin>py314t
Python 3.14.0a5 experimental free-threading build (tags/v3.14.0a5:3ae9101, Feb 11 2025, 17:44:01) [MSC v.1942 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyobject import getrefcount_nogil,setrefcount_nogil
>>> class A:pass
...
>>> a=A()
>>> getrefcount_nogil(a)
(1, 0) # the first is ob_ref_local and the second is ob_ref_shared
>>> def another_thread():
... b=a
... while True:pass
...
>>> from _thread import start_new_thread
>>> start_new_thread(another_thread,())
10824
>>> getrefcount_nogil(a)
(1, 5)
>>>
Snippet of getrefcount_nogil
from the source code of pyobject
:
PyObject *getrefcount_nogil(PyObject *self, PyObject *args){
PyObject *obj;
if (!PyArg_ParseTuple(args,"O",&obj)) return NULL;
PyObject *result = PyTuple_New(2); // Simply returns a tuple
PyTuple_SetItem(result, 0, PyLong_FromUnsignedLong(obj->ob_ref_local));
PyTuple_SetItem(result, 1, PyLong_FromSize_t(obj->ob_ref_shared));
return result;
}
So, what is the function and implication of ob_ref_local
and ob_ref_shared
values that replace ob_refcnt
?
Metadata
Metadata
Assignees
Labels
No labels