Skip to content

Commit 521db10

Browse files
committed
Add PyUnstable_Object_IsUniquelyReferenced
1 parent 718e12e commit 521db10

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

pythoncapi_compat.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,24 @@ PyConfig_GetInt(const char *name, int *value)
22112211
}
22122212
#endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION)
22132213

2214+
// gh-133144 added PyUnstable_Object_IsUniquelyReferenced() to Python 3.14.0b1
2215+
// Adapted from _PyObject_IsUniquelyReferenced implementation
2216+
#if PY_VERSION_HEX < 0x030E00B0
2217+
static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj)
2218+
{
2219+
#if !defined(Py_GIL_DISABLED)
2220+
return Py_REFCNT(obj) == 1;
2221+
#else
2222+
// NOTE: the entire ob_ref_shared field must be zero, including flags, to
2223+
// ensure that other threads cannot concurrently create new references to
2224+
// this object.
2225+
return (_Py_IsOwnedByCurrentThread(obj) &&
2226+
_Py_atomic_load_uint32_relaxed(&obj->ob_ref_local) == 1 &&
2227+
_Py_atomic_load_ssize_relaxed(&obj->ob_ref_shared) == 0);
2228+
#endif
2229+
}
2230+
#endif
2231+
22142232

22152233
#if PY_VERSION_HEX < 0x030F0000
22162234
static inline PyObject*

tests/test_pythoncapi_compat_cext.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,27 @@ test_unicodewriter_format(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
19721972
}
19731973
#endif
19741974

1975+
static PyObject *
1976+
test_uniquely_referenced(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
1977+
{
1978+
const char *str = "Hello World";
1979+
PyObject *obj = PyUnicode_FromString(str);
1980+
if (obj == NULL) {
1981+
return NULL;
1982+
}
1983+
1984+
assert(PyUnstable_Object_IsUniquelyReferenced(obj));
1985+
1986+
Py_INCREF(obj);
1987+
1988+
assert(!PyUnstable_Object_IsUniquelyReferenced(obj));
1989+
1990+
Py_DECREF(obj);
1991+
Py_DECREF(obj);
1992+
1993+
Py_RETURN_NONE;
1994+
}
1995+
19751996

19761997
static PyObject *
19771998
test_bytes(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
@@ -2328,6 +2349,7 @@ static struct PyMethodDef methods[] = {
23282349
{"test_config", test_config, METH_NOARGS, _Py_NULL},
23292350
#endif
23302351
{"test_sys", test_sys, METH_NOARGS, _Py_NULL},
2352+
{"test_uniquely_referenced", test_uniquely_referenced, METH_NOARGS, _Py_NULL},
23312353
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
23322354
};
23332355

0 commit comments

Comments
 (0)