Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc44469c

Browse files
Add PyUnstable_TryIncref() and PyUnstable_EnableTryIncRef() (#159)
Co-authored-by: Victor Stinner <vstinner@python.org>
1 parente510a7b commitc44469c

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

‎pythoncapi_compat.h‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,6 +2231,81 @@ static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj)
22312231
}
22322232
#endif
22332233

2234+
// gh-128926 added PyUnstable_TryIncRef() and PyUnstable_EnableTryIncRef() to
2235+
// Python 3.14.0a5. Adapted from _Py_TryIncref() and _PyObject_SetMaybeWeakref().
2236+
#if PY_VERSION_HEX < 0x030E00A5
2237+
staticinlineintPyUnstable_TryIncRef(PyObject *op)
2238+
{
2239+
#ifndef Py_GIL_DISABLED
2240+
if (Py_REFCNT(op) >0) {
2241+
Py_INCREF(op);
2242+
return1;
2243+
}
2244+
return0;
2245+
#else
2246+
// _Py_TryIncrefFast()
2247+
uint32_t local =_Py_atomic_load_uint32_relaxed(&op->ob_ref_local);
2248+
local +=1;
2249+
if (local ==0) {
2250+
// immortal
2251+
return1;
2252+
}
2253+
if (_Py_IsOwnedByCurrentThread(op)) {
2254+
_Py_INCREF_STAT_INC();
2255+
_Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local);
2256+
#ifdef Py_REF_DEBUG
2257+
_Py_INCREF_IncRefTotal();
2258+
#endif
2259+
return1;
2260+
}
2261+
2262+
// _Py_TryIncRefShared()
2263+
Py_ssize_t shared =_Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
2264+
for (;;) {
2265+
// If the shared refcount is zero and the object is either merged
2266+
// or may not have weak references, then we cannot incref it.
2267+
if (shared ==0 || shared == _Py_REF_MERGED) {
2268+
return0;
2269+
}
2270+
2271+
if (_Py_atomic_compare_exchange_ssize(
2272+
&op->ob_ref_shared,
2273+
&shared,
2274+
shared + (1 << _Py_REF_SHARED_SHIFT))) {
2275+
#ifdef Py_REF_DEBUG
2276+
_Py_INCREF_IncRefTotal();
2277+
#endif
2278+
_Py_INCREF_STAT_INC();
2279+
return1;
2280+
}
2281+
}
2282+
#endif
2283+
}
2284+
2285+
staticinlinevoidPyUnstable_EnableTryIncRef(PyObject *op)
2286+
{
2287+
#ifdef Py_GIL_DISABLED
2288+
// _PyObject_SetMaybeWeakref()
2289+
if (_Py_IsImmortal(op)) {
2290+
return;
2291+
}
2292+
for (;;) {
2293+
Py_ssize_t shared =_Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
2294+
if ((shared & _Py_REF_SHARED_FLAG_MASK) !=0) {
2295+
// Nothing to do if it's in WEAKREFS, QUEUED, or MERGED states.
2296+
return;
2297+
}
2298+
if (_Py_atomic_compare_exchange_ssize(
2299+
&op->ob_ref_shared, &shared, shared | _Py_REF_MAYBE_WEAKREF)) {
2300+
return;
2301+
}
2302+
}
2303+
#else
2304+
(void)op;// unused argument
2305+
#endif
2306+
}
2307+
#endif
2308+
22342309

22352310
#if PY_VERSION_HEX < 0x030F0000
22362311
staticinline PyObject*

‎tests/test_pythoncapi_compat_cext.c‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,6 +2448,46 @@ test_tuple(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
24482448
returntest_tuple_fromarray();
24492449
}
24502450

2451+
// Test adapted from CPython's _testcapi/object.c
2452+
staticintTryIncref_dealloc_called=0;
2453+
2454+
staticvoid
2455+
TryIncref_dealloc(PyObject*op)
2456+
{
2457+
// PyUnstable_TryIncRef should return 0 if object is being deallocated
2458+
assert(Py_REFCNT(op)==0);
2459+
assert(!PyUnstable_TryIncRef(op));
2460+
assert(Py_REFCNT(op)==0);
2461+
2462+
TryIncref_dealloc_called++;
2463+
Py_TYPE(op)->tp_free(op);
2464+
}
2465+
2466+
staticPyTypeObjectTryIncrefType;
2467+
2468+
staticPyObject*
2469+
test_try_incref(PyObject*Py_UNUSED(module),PyObject*Py_UNUSED(args))
2470+
{
2471+
TryIncref_dealloc_called=0;
2472+
2473+
PyObject*obj=PyObject_New(PyObject,&TryIncrefType);
2474+
if (obj==_Py_NULL) {
2475+
return_Py_NULL;
2476+
}
2477+
2478+
PyUnstable_EnableTryIncRef(obj);
2479+
2480+
Py_ssize_trefcount=Py_REFCNT(obj);
2481+
assert(PyUnstable_TryIncRef(obj));
2482+
assert(Py_REFCNT(obj)==refcount+1);
2483+
2484+
Py_DECREF(obj);
2485+
Py_DECREF(obj);
2486+
2487+
assert(TryIncref_dealloc_called==1);
2488+
Py_RETURN_NONE;
2489+
}
2490+
24512491

24522492
staticstructPyMethodDefmethods[]= {
24532493
{"test_object",test_object,METH_NOARGS,_Py_NULL},
@@ -2504,6 +2544,7 @@ static struct PyMethodDef methods[] = {
25042544
{"test_uniquely_referenced",test_uniquely_referenced,METH_NOARGS,_Py_NULL},
25052545
{"test_byteswriter",test_byteswriter,METH_NOARGS,_Py_NULL},
25062546
{"test_tuple",test_tuple,METH_NOARGS,_Py_NULL},
2547+
{"test_try_incref",test_try_incref,METH_NOARGS,_Py_NULL},
25072548
{_Py_NULL,_Py_NULL,0,_Py_NULL}
25082549
};
25092550

@@ -2532,6 +2573,13 @@ module_exec(PyObject *module)
25322573
return-1;
25332574
}
25342575
#endif
2576+
TryIncrefType.tp_name="TryIncrefType";
2577+
TryIncrefType.tp_basicsize=sizeof(PyObject);
2578+
TryIncrefType.tp_dealloc=TryIncref_dealloc;
2579+
TryIncrefType.tp_free=PyObject_Del;
2580+
if (PyType_Ready(&TryIncrefType)<0) {
2581+
return-1;
2582+
}
25352583
return0;
25362584
}
25372585

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp