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

Appearance settings

Commit eda29bc

Browse filesBrowse files
committed
gh-112087: Update list_get_item_ref to optimistically avoid locking
1 parent cbf3d38 commit eda29bc
Copy full SHA for eda29bc

File tree

1 file changed

+60
-0
lines changed
Filter options

1 file changed

+60
-0
lines changed

‎Objects/listobject.c

Copy file name to clipboardExpand all lines: Objects/listobject.c
+60Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,65 @@ PyList_GetItemRef(PyObject *op, Py_ssize_t i)
263263
return Py_NewRef(PyList_GET_ITEM(op, i));
264264
}
265265

266+
#ifdef Py_GIL_DISABLED
267+
268+
static PyObject *
269+
list_item_impl(PyListObject *self, Py_ssize_t idx, PyObject *dead)
270+
{
271+
PyObject *item = NULL;
272+
Py_BEGIN_CRITICAL_SECTION(self);
273+
if (!_PyObject_GC_IS_SHARED(self)) {
274+
_PyObject_GC_SET_SHARED(self);
275+
}
276+
Py_ssize_t size = Py_SIZE(self);
277+
if (!valid_index(idx, size)) {
278+
goto exit;
279+
}
280+
item = Py_NewRef(self->ob_item[idx]);
281+
exit:
282+
Py_END_CRITICAL_SECTION();
283+
return item;
284+
}
285+
286+
static inline PyObject*
287+
list_get_item_ref(PyListObject *op, Py_ssize_t i)
288+
{
289+
if (!_Py_IsOwnedByCurrentThread((PyObject *)op) && !_PyObject_GC_IS_SHARED(op)) {
290+
return list_item_impl(op, i, NULL);
291+
}
292+
// Need atomic operation for the getting size.
293+
Py_ssize_t size = _Py_atomic_load_ssize_relaxed(&_PyVarObject_CAST(op)->ob_size);
294+
if (!valid_index(i, size)) {
295+
return NULL;
296+
}
297+
PyObject **ob_item = _Py_atomic_load_ptr(&op->ob_item);
298+
if (ob_item == NULL) {
299+
return NULL;
300+
}
301+
Py_ssize_t cap = _Py_atomic_load_ssize_relaxed(&op->allocated);
302+
if (!valid_index(i, cap)) {
303+
return NULL;
304+
}
305+
PyObject *item = _Py_atomic_load_ptr(&ob_item[i]);
306+
if (mi_unlikely(!item)) {
307+
return list_item_impl(op, i, NULL);
308+
}
309+
if (mi_likely(_Py_TryIncrefFast(item))) {
310+
goto compare_ob_item;
311+
}
312+
if (!_Py_TryIncRefShared(item)) {
313+
return list_item_impl(op, i, item);
314+
}
315+
if (mi_unlikely(item != _Py_atomic_load_ptr(&ob_item[i]))) {
316+
return list_item_impl(op, i, item);
317+
}
318+
compare_ob_item:
319+
if (mi_unlikely(ob_item != _Py_atomic_load_ptr(&op->ob_item))) {
320+
return list_item_impl(op, i, item);
321+
}
322+
return item;
323+
}
324+
#else
266325
static inline PyObject*
267326
list_get_item_ref(PyListObject *op, Py_ssize_t i)
268327
{
@@ -271,6 +330,7 @@ list_get_item_ref(PyListObject *op, Py_ssize_t i)
271330
}
272331
return Py_NewRef(PyList_GET_ITEM(op, i));
273332
}
333+
#endif
274334

275335
int
276336
PyList_SetItem(PyObject *op, Py_ssize_t i,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.