Skip to content

Commit 6a64489

Browse files
committed
Unify lock allocation and GIL release thresholds
XXHASH_LOCK_MAYBE_INIT allocated the lock at >= XXHASH_GIL_MINSIZE while every GIL release check uses >, so an update of exactly 64KB allocated a lock that was never used. Align both at > XXHASH_GIL_MINSIZE and update the README wording.
1 parent b274f52 commit 6a64489

2 files changed

Lines changed: 4 additions & 4 deletions

File tree

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ One-shot functions (``xxh32_digest``, ``xxh64_hexdigest``, ``xxh3_128_digest``,
264264
etc.) are stateless and always safe to call concurrently.
265265

266266
On Python 3.13+ the lock is always active. On Python 3.9-3.12 the lock is
267-
created on the first ``update()`` of 64KB or more; smaller operations never
268-
release the GIL, so they are serialized by the GIL itself.
267+
created on the first ``update()`` of more than 64KB; operations of 64KB or
268+
less never release the GIL, so they are serialized by the GIL itself.
269269

270270
Sharing a streaming hash object across threads is still discouraged: even
271271
with locking, the order in which concurrent updates are applied (and hence

src/_xxhash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@
4747
# define XXHASH_LOCK_FIELD PyThread_type_lock lock;
4848
# define XXHASH_LOCK_INIT(o) ((o)->lock = NULL)
4949
# define XXHASH_LOCK_IS_ACTIVE(o) ((o)->lock != NULL)
50-
/* Lazy allocation on first large update */
50+
/* Lazy allocation on first update large enough to release the GIL */
5151
# define XXHASH_LOCK_MAYBE_INIT(o, len) \
5252
do { \
53-
if ((o)->lock == NULL && (len) >= XXHASH_GIL_MINSIZE) { \
53+
if ((o)->lock == NULL && (len) > XXHASH_GIL_MINSIZE) { \
5454
(o)->lock = PyThread_allocate_lock(); \
5555
/* fail? lock stays NULL, fall back to non-threaded code. */ \
5656
} \

0 commit comments

Comments
 (0)