|
1 | 1 | #include "Python.h"
|
2 |
| -#include "pycore_call.h" // _PyObject_CallNoArgs() |
3 |
| -#include "pycore_ceval.h" // _PyEval_GetBuiltin() |
4 |
| -#include "pycore_long.h" // _PyLong_GetZero() |
5 |
| -#include "pycore_moduleobject.h" // _PyModule_GetState() |
6 |
| -#include "pycore_typeobject.h" // _PyType_GetModuleState() |
7 |
| -#include "pycore_object.h" // _PyObject_GC_TRACK() |
8 |
| -#include "pycore_tuple.h" // _PyTuple_ITEMS() |
| 2 | +#include "pycore_call.h" // _PyObject_CallNoArgs() |
| 3 | +#include "pycore_ceval.h" // _PyEval_GetBuiltin() |
| 4 | +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION() |
| 5 | +#include "pycore_long.h" // _PyLong_GetZero() |
| 6 | +#include "pycore_moduleobject.h" // _PyModule_GetState() |
| 7 | +#include "pycore_typeobject.h" // _PyType_GetModuleState() |
| 8 | +#include "pycore_object.h" // _PyObject_GC_TRACK() |
| 9 | +#include "pycore_tuple.h" // _PyTuple_ITEMS() |
9 | 10 |
|
10 |
| -#include <stddef.h> // offsetof() |
| 11 | +#include <stddef.h> // offsetof() |
11 | 12 |
|
12 | 13 | /* Itertools module written and maintained
|
13 | 14 | by Raymond D. Hettinger <python@rcn.com>
|
@@ -4037,7 +4038,7 @@ fast_mode: when cnt an integer < PY_SSIZE_T_MAX and no step is specified.
|
4037 | 4038 |
|
4038 | 4039 | assert(cnt != PY_SSIZE_T_MAX && long_cnt == NULL && long_step==PyLong(1));
|
4039 | 4040 | Advances with: cnt += 1
|
4040 |
| - When count hits Y_SSIZE_T_MAX, switch to slow_mode. |
| 4041 | + When count hits PY_SSIZE_T_MAX, switch to slow_mode. |
4041 | 4042 |
|
4042 | 4043 | slow_mode: when cnt == PY_SSIZE_T_MAX, step is not int(1), or cnt is a float.
|
4043 | 4044 |
|
@@ -4186,9 +4187,30 @@ count_nextlong(countobject *lz)
|
4186 | 4187 | static PyObject *
|
4187 | 4188 | count_next(countobject *lz)
|
4188 | 4189 | {
|
| 4190 | +#ifndef Py_GIL_DISABLED |
4189 | 4191 | if (lz->cnt == PY_SSIZE_T_MAX)
|
4190 | 4192 | return count_nextlong(lz);
|
4191 | 4193 | return PyLong_FromSsize_t(lz->cnt++);
|
| 4194 | +#else |
| 4195 | + // free-threading version |
| 4196 | + // fast mode uses compare-exchange loop |
| 4197 | + // slow mode uses a critical section |
| 4198 | + PyObject *returned; |
| 4199 | + Py_ssize_t cnt; |
| 4200 | + |
| 4201 | + cnt = _Py_atomic_load_ssize_relaxed(&lz->cnt); |
| 4202 | + for (;;) { |
| 4203 | + if (cnt == PY_SSIZE_T_MAX) { |
| 4204 | + Py_BEGIN_CRITICAL_SECTION(lz); |
| 4205 | + returned = count_nextlong(lz); |
| 4206 | + Py_END_CRITICAL_SECTION(); |
| 4207 | + return returned; |
| 4208 | + } |
| 4209 | + if (_Py_atomic_compare_exchange_ssize(&lz->cnt, &cnt, cnt + 1)) { |
| 4210 | + return PyLong_FromSsize_t(cnt); |
| 4211 | + } |
| 4212 | + } |
| 4213 | +#endif |
4192 | 4214 | }
|
4193 | 4215 |
|
4194 | 4216 | static PyObject *
|
|
0 commit comments