|
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>
|
@@ -3254,7 +3255,7 @@ fast_mode: when cnt an integer < PY_SSIZE_T_MAX and no step is specified.
|
3254 | 3255 |
|
3255 | 3256 | assert(cnt != PY_SSIZE_T_MAX && long_cnt == NULL && long_step==PyLong(1));
|
3256 | 3257 | Advances with: cnt += 1
|
3257 |
| - When count hits Y_SSIZE_T_MAX, switch to slow_mode. |
| 3258 | + When count hits PY_SSIZE_T_MAX, switch to slow_mode. |
3258 | 3259 |
|
3259 | 3260 | slow_mode: when cnt == PY_SSIZE_T_MAX, step is not int(1), or cnt is a float.
|
3260 | 3261 |
|
@@ -3403,9 +3404,30 @@ count_nextlong(countobject *lz)
|
3403 | 3404 | static PyObject *
|
3404 | 3405 | count_next(countobject *lz)
|
3405 | 3406 | {
|
| 3407 | +#ifndef Py_GIL_DISABLED |
3406 | 3408 | if (lz->cnt == PY_SSIZE_T_MAX)
|
3407 | 3409 | return count_nextlong(lz);
|
3408 | 3410 | return PyLong_FromSsize_t(lz->cnt++);
|
| 3411 | +#else |
| 3412 | + // free-threading version |
| 3413 | + // fast mode uses compare-exchange loop |
| 3414 | + // slow mode uses a critical section |
| 3415 | + PyObject *returned; |
| 3416 | + Py_ssize_t cnt; |
| 3417 | + |
| 3418 | + cnt = _Py_atomic_load_ssize_relaxed(&lz->cnt); |
| 3419 | + for (;;) { |
| 3420 | + if (cnt == PY_SSIZE_T_MAX) { |
| 3421 | + Py_BEGIN_CRITICAL_SECTION(lz); |
| 3422 | + returned = count_nextlong(lz); |
| 3423 | + Py_END_CRITICAL_SECTION(); |
| 3424 | + return returned; |
| 3425 | + } |
| 3426 | + if (_Py_atomic_compare_exchange_ssize(&lz->cnt, &cnt, cnt + 1)) { |
| 3427 | + return PyLong_FromSsize_t(cnt); |
| 3428 | + } |
| 3429 | + } |
| 3430 | +#endif |
3409 | 3431 | }
|
3410 | 3432 |
|
3411 | 3433 | static PyObject *
|
|
0 commit comments