Skip to content

Commit 15c8015

Browse files
committed
factored out macros for diable/reenable list
1 parent d178d66 commit 15c8015

File tree

1 file changed

+50
-52
lines changed

1 file changed

+50
-52
lines changed

Objects/listobject.c

Lines changed: 50 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,6 +2870,48 @@ unsafe_tuple_compare(PyObject *v, PyObject *w, MergeState *ms)
28702870
return PyObject_RichCompareBool(vt->ob_item[i], wt->ob_item[i], Py_LT);
28712871
}
28722872

2873+
#define DISABLE_LIST(self, saved_ob_size, saved_ob_item, saved_allocated) \
2874+
do { \
2875+
saved_ob_size = Py_SIZE(self); \
2876+
saved_ob_item = self->ob_item; \
2877+
saved_allocated = self->allocated; \
2878+
Py_SET_SIZE(self, 0); \
2879+
FT_ATOMIC_STORE_PTR_RELEASE(self->ob_item, NULL); \
2880+
self->allocated = -1; /* any operation will reset it to >= 0 */ \
2881+
} while (0)
2882+
2883+
#ifdef Py_GIL_DISABLED
2884+
#define _REENABLE_LIST_GIL_PART(self, use_qsbr) \
2885+
do { \
2886+
ensure_shared_on_resize(self); \
2887+
use_qsbr = _PyObject_GC_IS_SHARED(self); \
2888+
} while (0)
2889+
#else
2890+
#define _REENABLE_LIST_GIL_PART(self, use_qsbr) \
2891+
do { \
2892+
use_qsbr = false; \
2893+
} while (0)
2894+
#endif
2895+
2896+
#define REENABLE_LIST(self, saved_ob_size, saved_ob_item, saved_allocated) \
2897+
do { \
2898+
final_ob_item = self->ob_item; \
2899+
i = Py_SIZE(self); \
2900+
Py_SET_SIZE(self, saved_ob_size); \
2901+
FT_ATOMIC_STORE_PTR_RELEASE(self->ob_item, saved_ob_item); \
2902+
FT_ATOMIC_STORE_SSIZE_RELAXED(self->allocated, saved_allocated); \
2903+
if (final_ob_item != NULL) { \
2904+
/* we cannot use list_clear() for this because it does not */ \
2905+
/* guarantee that the list is really empty when it returns */ \
2906+
while (--i >= 0) { \
2907+
Py_XDECREF(final_ob_item[i]); \
2908+
} \
2909+
bool use_qsbr; \
2910+
_REENABLE_LIST_GIL_PART(self, use_qsbr); \
2911+
free_list_items(final_ob_item, use_qsbr); \
2912+
} \
2913+
} while (0)
2914+
28732915
/* An adaptive, stable, natural mergesort. See listsort.txt.
28742916
* Returns Py_None on success, NULL on error. Even in case of error, the
28752917
* list will be some permutation of its input state (nothing is lost or
@@ -2943,12 +2985,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, PyObject *keylist,
29432985
* sorting (allowing mutations during sorting is a core-dump
29442986
* factory, since ob_item may change).
29452987
*/
2946-
saved_ob_size = Py_SIZE(self);
2947-
saved_ob_item = self->ob_item;
2948-
saved_allocated = self->allocated;
2949-
Py_SET_SIZE(self, 0);
2950-
FT_ATOMIC_STORE_PTR_RELEASE(self->ob_item, NULL);
2951-
self->allocated = -1; /* any operation will reset it to >= 0 */
2988+
DISABLE_LIST(self, saved_ob_size, saved_ob_item, saved_allocated);
29522989

29532990
if (keyfunc == NULL && keylist == NULL) {
29542991
keys = NULL;
@@ -2987,14 +3024,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, PyObject *keylist,
29873024
goto keyfunc_fail;
29883025
}
29893026
self_kl = ((PyListObject *) keylist);
2990-
// Disable keylist modifications via same methodology as for main list
2991-
keylist_ob_size = Py_SIZE(self_kl);
2992-
keylist_ob_item = self_kl->ob_item;
2993-
keylist_allocated = self_kl->allocated;
2994-
Py_SET_SIZE(self_kl, 0);
2995-
FT_ATOMIC_STORE_PTR_RELEASE(self_kl->ob_item, NULL);
2996-
self_kl->allocated = -1; /* any operation will reset it to >= 0 */
2997-
3027+
DISABLE_LIST(self_kl, keylist_ob_size, keylist_ob_item, keylist_allocated);
29983028
keylist_frozen = 1;
29993029
if (saved_ob_size != keylist_ob_size) {
30003030
PyErr_SetString(PyExc_ValueError,
@@ -3196,49 +3226,17 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, PyObject *keylist,
31963226
if (reverse && saved_ob_size > 1)
31973227
reverse_slice(keylist_ob_item, keylist_ob_item + keylist_ob_size);
31983228

3199-
final_ob_item = self_kl->ob_item;
3200-
i = Py_SIZE(self_kl);
3201-
Py_SET_SIZE(self_kl, keylist_ob_size);
3202-
FT_ATOMIC_STORE_PTR_RELEASE(self_kl->ob_item, keylist_ob_item);
3203-
FT_ATOMIC_STORE_SSIZE_RELAXED(self_kl->allocated, keylist_allocated);
3204-
if (final_ob_item != NULL) {
3205-
/* we cannot use list_clear() for this because it does not
3206-
guarantee that the list is really empty when it returns */
3207-
while (--i >= 0) {
3208-
Py_XDECREF(final_ob_item[i]);
3209-
}
3210-
#ifdef Py_GIL_DISABLED
3211-
ensure_shared_on_resize(self_kl);
3212-
bool use_qsbr = _PyObject_GC_IS_SHARED(self_kl);
3213-
#else
3214-
bool use_qsbr = false;
3215-
#endif
3216-
free_list_items(final_ob_item, use_qsbr);
3217-
}
3229+
REENABLE_LIST(self_kl, keylist_ob_size, keylist_ob_item, keylist_allocated);
3230+
final_ob_item = NULL;
32183231
}
32193232

32203233
keyfunc_fail:
3221-
final_ob_item = self->ob_item;
3222-
i = Py_SIZE(self);
3223-
Py_SET_SIZE(self, saved_ob_size);
3224-
FT_ATOMIC_STORE_PTR_RELEASE(self->ob_item, saved_ob_item);
3225-
FT_ATOMIC_STORE_SSIZE_RELAXED(self->allocated, saved_allocated);
3226-
if (final_ob_item != NULL) {
3227-
/* we cannot use list_clear() for this because it does not
3228-
guarantee that the list is really empty when it returns */
3229-
while (--i >= 0) {
3230-
Py_XDECREF(final_ob_item[i]);
3231-
}
3232-
#ifdef Py_GIL_DISABLED
3233-
ensure_shared_on_resize(self);
3234-
bool use_qsbr = _PyObject_GC_IS_SHARED(self);
3235-
#else
3236-
bool use_qsbr = false;
3237-
#endif
3238-
free_list_items(final_ob_item, use_qsbr);
3239-
}
3234+
REENABLE_LIST(self, saved_ob_size, saved_ob_item, saved_allocated);
32403235
return Py_XNewRef(result);
32413236
}
3237+
#undef DISABLE_LIST
3238+
#undef _REENABLE_LIST_GIL_PART
3239+
#undef REENABLE_LIST
32423240
#undef IFLT
32433241
#undef ISLT
32443242

0 commit comments

Comments
 (0)