qfcy
qfcy

Reputation: 145

Why does Python 3.14 use ob_ref_local and ob_ref_shared for reference counts when GIL is absent

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, 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)
>>>

So, what is the function and implication of ob_ref_local and ob_ref_shared values that replace ob_refcnt?

Upvotes: 1

Views: 40

Answers (1)

user29664827
user29664827

Reputation: 61

The documentation of new reference counting features can be found in peps.python.org/pep-0703/#reference-counting.

According to the PEP, in biased reference counting that assumes most objects are linked to one owning thread, the owning thread utilize non-atomic instructions to adjust the local reference count, while other threads employ atomic instructions to modify the shared reference count.

Upvotes: 1

Related Questions