Skip to content

Commit 98cfd06

Browse files
Update stats to use atomic ops (#54)
1 parent 792ed6f commit 98cfd06

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed

pkg/net/credentials/alts/handshake/handshake_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ func TestHandshakerConcurrentHandshakes(t *testing.T) {
435435
}
436436

437437
// Verify concurrent handshake limits
438-
require.LessOrEqual(t, stat.MaxConcurrentCalls, maxConcurrentHandshakes,
438+
require.LessOrEqual(t, stat.GetMaxConcurrentCalls(), maxConcurrentHandshakes,
439439
"concurrent handshakes exceeded limit")
440440
})
441441
}

pkg/net/credentials/alts/testutil/testutil.go

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,49 @@ package testutil
44
import (
55
"encoding/binary"
66
"net"
7-
"sync"
7+
"sync/atomic"
88
"time"
99

1010
. "github.com/LumeraProtocol/supernode/pkg/net/credentials/alts/common"
1111
)
1212

1313
// Stats is used to collect statistics about concurrent handshake calls.
1414
type Stats struct {
15-
mu sync.Mutex
16-
calls int
17-
MaxConcurrentCalls int
15+
calls int32
16+
maxConcurrentCalls int32
1817
}
1918

2019
// Update updates the statistics by adding one call.
2120
func (s *Stats) Update() func() {
22-
s.mu.Lock()
23-
s.calls++
24-
if s.calls > s.MaxConcurrentCalls {
25-
s.MaxConcurrentCalls = s.calls
21+
// Atomically increment calls
22+
newCalls := atomic.AddInt32(&s.calls, 1)
23+
24+
// Update MaxConcurrentCalls if needed
25+
for {
26+
currentMax := atomic.LoadInt32(&s.maxConcurrentCalls)
27+
if newCalls <= currentMax {
28+
break
29+
}
30+
if atomic.CompareAndSwapInt32(&s.maxConcurrentCalls, currentMax, newCalls) {
31+
break
32+
}
2633
}
27-
s.mu.Unlock()
2834

2935
return func() {
30-
s.mu.Lock()
31-
s.calls--
32-
s.mu.Unlock()
36+
// Atomically decrement calls
37+
atomic.AddInt32(&s.calls, -1)
3338
}
3439
}
3540

3641
// Reset resets the statistics.
3742
func (s *Stats) Reset() {
38-
s.mu.Lock()
39-
defer s.mu.Unlock()
40-
s.calls = 0
41-
s.MaxConcurrentCalls = 0
43+
atomic.StoreInt32(&s.calls, 0)
44+
atomic.StoreInt32(&s.maxConcurrentCalls, 0)
45+
}
46+
47+
// GetMaxConcurrentCalls returns the maximum number of concurrent calls.
48+
func (s *Stats) GetMaxConcurrentCalls() int {
49+
return int(atomic.LoadInt32(&s.maxConcurrentCalls))
4250
}
4351

4452
// testConn mimics a net.Conn to the peer.
@@ -50,7 +58,7 @@ type testLatencyConn struct {
5058
// NewTestConnWithReadLatency wraps a net.Conn with artificial read latency
5159
func NewTestConnWithReadLatency(conn net.Conn, readLatency time.Duration) net.Conn {
5260
return &testLatencyConn{
53-
Conn: conn,
61+
Conn: conn,
5462
readLatency: readLatency,
5563
}
5664
}
@@ -87,9 +95,9 @@ func NewUnresponsiveTestConn(delay time.Duration) net.Conn {
8795

8896
// Read reads from the in buffer.
8997
func (c *unresponsiveTestConn) Read([]byte) (n int, err error) {
90-
// Wait for delay to simulate network latency
91-
time.Sleep(c.delay)
92-
// Return empty data (success but zero bytes)
98+
// Wait for delay to simulate network latency
99+
time.Sleep(c.delay)
100+
// Return empty data (success but zero bytes)
93101
return 0, nil
94102
}
95103

0 commit comments

Comments
 (0)