Skip to content

Commit 78ff37e

Browse files
committed
Add PyUnstable_Object_IsUniquelyReferenced
1 parent 5e31710 commit 78ff37e

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(ob) == 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
@@ -1953,6 +1953,27 @@ test_unicodewriter_format(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
19531953
}
19541954
#endif
19551955

1956+
static PyObject *
1957+
test_uniquely_referenced(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
1958+
{
1959+
const char *str = "Hello World";
1960+
PyObject *obj = PyUnicode_FromString(str);
1961+
if (obj == NULL) {
1962+
return NULL;
1963+
}
1964+
1965+
assert(PyUnstable_Object_IsUniquelyReferenced(obj));
1966+
1967+
Py_INCREF(obj);
1968+
1969+
assert(!PyUnstable_Object_IsUniquelyReferenced(obj));
1970+
1971+
Py_DECREF(obj);
1972+
Py_DECREF(obj);
1973+
1974+
Py_RETURN_NONE;
1975+
}
1976+
19561977

19571978
static PyObject *
19581979
test_bytes(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
@@ -2309,6 +2330,7 @@ static struct PyMethodDef methods[] = {
23092330
{"test_config", test_config, METH_NOARGS, _Py_NULL},
23102331
#endif
23112332
{"test_sys", test_sys, METH_NOARGS, _Py_NULL},
2333+
{"test_uniquely_referenced", test_uniquely_referenced, METH_NOARGS, _Py_NULL},
23122334
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
23132335
};
23142336

0 commit comments

Comments
 (0)