From 39111e9226297fb11f21cbb0c9022314ca0fa0e1 Mon Sep 17 00:00:00 2001 From: Fantix King Date: Thu, 15 Jan 2026 13:02:22 -0500 Subject: [PATCH 1/2] debug: use C __atomic builtins for counters --- uvloop/cbhandles.pyx | 6 ++++-- uvloop/includes/system.pxd | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/uvloop/cbhandles.pyx b/uvloop/cbhandles.pyx index 2914b42e..42763e3d 100644 --- a/uvloop/cbhandles.pyx +++ b/uvloop/cbhandles.pyx @@ -10,7 +10,8 @@ cdef class Handle: self.loop = loop if UVLOOP_DEBUG: loop._debug_cb_handles_total += 1 - loop._debug_cb_handles_count += 1 + system.__atomic_fetch_add( + &loop._debug_cb_handles_count, 1, system.__ATOMIC_RELAXED) if loop._debug: self._source_traceback = extract_stack() @@ -21,7 +22,8 @@ cdef class Handle: def __dealloc__(self): if UVLOOP_DEBUG and self.loop is not None: - self.loop._debug_cb_handles_count -= 1 + system.__atomic_fetch_sub( + &self.loop._debug_cb_handles_count, 1, system.__ATOMIC_RELAXED) if self.loop is None: raise RuntimeError('Handle.loop is None in Handle.__dealloc__') diff --git a/uvloop/includes/system.pxd b/uvloop/includes/system.pxd index 367fedd1..89d0e327 100644 --- a/uvloop/includes/system.pxd +++ b/uvloop/includes/system.pxd @@ -94,3 +94,11 @@ cdef extern from "includes/fork_handler.h": void setForkHandler(OnForkHandler handler) void resetForkHandler() void setMainThreadID(uint64_t id) + + +cdef extern from * nogil: + uint64_t __atomic_fetch_add(uint64_t *ptr, uint64_t val, int memorder) + uint64_t __atomic_fetch_sub(uint64_t *ptr, uint64_t val, int memorder) + + cdef enum: + __ATOMIC_RELAXED From 4d566385f061b743b536d781e3a06e9b6abbfaac Mon Sep 17 00:00:00 2001 From: Fantix King Date: Thu, 15 Jan 2026 13:19:40 -0500 Subject: [PATCH 2/2] Also apply on timer handles --- uvloop/cbhandles.pyx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/uvloop/cbhandles.pyx b/uvloop/cbhandles.pyx index 42763e3d..00070816 100644 --- a/uvloop/cbhandles.pyx +++ b/uvloop/cbhandles.pyx @@ -9,7 +9,8 @@ cdef class Handle: cdef inline _set_loop(self, Loop loop): self.loop = loop if UVLOOP_DEBUG: - loop._debug_cb_handles_total += 1 + system.__atomic_fetch_add( + &loop._debug_cb_handles_total, 1, system.__ATOMIC_RELAXED) system.__atomic_fetch_add( &loop._debug_cb_handles_count, 1, system.__ATOMIC_RELAXED) if loop._debug: @@ -176,8 +177,10 @@ cdef class TimerHandle: self._cancelled = 0 if UVLOOP_DEBUG: - self.loop._debug_cb_timer_handles_total += 1 - self.loop._debug_cb_timer_handles_count += 1 + system.__atomic_fetch_add( + &self.loop._debug_cb_timer_handles_total, 1, system.__ATOMIC_RELAXED) + system.__atomic_fetch_add( + &self.loop._debug_cb_timer_handles_count, 1, system.__ATOMIC_RELAXED) if context is None: context = Context_CopyCurrent() @@ -207,7 +210,8 @@ cdef class TimerHandle: def __dealloc__(self): if UVLOOP_DEBUG: - self.loop._debug_cb_timer_handles_count -= 1 + system.__atomic_fetch_sub( + &self.loop._debug_cb_timer_handles_count, 1, system.__ATOMIC_RELAXED) if self.timer is not None: raise RuntimeError('active TimerHandle is deallacating')