From 20aa85037dfa15f45d16e1a91c13f80dfb10a91f Mon Sep 17 00:00:00 2001 From: Nedyalko Dyakov Date: Mon, 10 Nov 2025 16:22:56 +0200 Subject: [PATCH] address linter and tests --- internal/pool/conn_state.go | 23 +++++++++++++---------- internal/semaphore.go | 6 ------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/internal/pool/conn_state.go b/internal/pool/conn_state.go index a3c3a57f..2050a742 100644 --- a/internal/pool/conn_state.go +++ b/internal/pool/conn_state.go @@ -218,17 +218,20 @@ func (sm *ConnStateMachine) AwaitAndTransition( targetState ConnState, ) (ConnState, error) { // Fast path: try immediate transition with CAS to prevent race conditions - for _, fromState := range validFromStates { - // Check if we're already in target state - if fromState == targetState && sm.GetState() == targetState { - return targetState, nil - } + // BUT: only if there are no waiters in the queue (to maintain FIFO ordering) + if sm.waiterCount.Load() == 0 { + for _, fromState := range validFromStates { + // Check if we're already in target state + if fromState == targetState && sm.GetState() == targetState { + return targetState, nil + } - // Try to atomically swap from fromState to targetState - if sm.state.CompareAndSwap(uint32(fromState), uint32(targetState)) { - // Success! We transitioned atomically - sm.notifyWaiters() - return targetState, nil + // Try to atomically swap from fromState to targetState + if sm.state.CompareAndSwap(uint32(fromState), uint32(targetState)) { + // Success! We transitioned atomically + sm.notifyWaiters() + return targetState, nil + } } } diff --git a/internal/semaphore.go b/internal/semaphore.go index 4c681482..a1dfca5f 100644 --- a/internal/semaphore.go +++ b/internal/semaphore.go @@ -14,12 +14,6 @@ var semTimers = sync.Pool{ }, } -// waiter represents a goroutine waiting for a token. -type waiter struct { - ready chan struct{} - next *waiter -} - // FastSemaphore is a channel-based semaphore optimized for performance. // It uses a fast path that avoids timer allocation when tokens are available. // The channel is pre-filled with tokens: Acquire = receive, Release = send.