Skip to content

Commit e78afb9

Browse files
Use thread safe sync.map
1 parent 636ded4 commit e78afb9

File tree

2 files changed

+29
-24
lines changed

2 files changed

+29
-24
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,7 @@ func TestHandshakerConcurrentHandshakes(t *testing.T) {
434434
"expected %d successful handshakes", maxConcurrentHandshakes*2)
435435
}
436436

437-
// Verify concurrent handshake limits
438-
require.LessOrEqual(t, stat.MaxConcurrentCalls, maxConcurrentHandshakes,
437+
require.LessOrEqual(t, stat.MaxConcurrentCalls(), maxConcurrentHandshakes,
439438
"concurrent handshakes exceeded limit")
440439
})
441440
}

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

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,46 @@ import (
55
"encoding/binary"
66
"net"
77
"sync"
8+
"sync/atomic"
89
"time"
910

1011
. "github.com/LumeraProtocol/supernode/pkg/net/credentials/alts/common"
1112
)
1213

1314
// Stats is used to collect statistics about concurrent handshake calls.
1415
type Stats struct {
15-
mu sync.Mutex
16-
calls int
17-
MaxConcurrentCalls int
16+
stats sync.Map
17+
callCount int64
18+
maxCalls int64
1819
}
1920

2021
// Update updates the statistics by adding one call.
21-
func (s *Stats) Update() func() {
22-
s.mu.Lock()
23-
s.calls++
24-
if s.calls > s.MaxConcurrentCalls {
25-
s.MaxConcurrentCalls = s.calls
22+
func (s *Stats) Update() {
23+
// Use atomic operations for counters
24+
current := atomic.AddInt64(&s.callCount, 1)
25+
26+
// Update max if needed
27+
for {
28+
max := atomic.LoadInt64(&s.maxCalls)
29+
if current <= max {
30+
break
31+
}
32+
if atomic.CompareAndSwapInt64(&s.maxCalls, max, current) {
33+
break
34+
}
2635
}
27-
s.mu.Unlock()
2836

29-
return func() {
30-
s.mu.Lock()
31-
s.calls--
32-
s.mu.Unlock()
33-
}
3437
}
3538

3639
// Reset resets the statistics.
3740
func (s *Stats) Reset() {
38-
s.mu.Lock()
39-
defer s.mu.Unlock()
40-
s.calls = 0
41-
s.MaxConcurrentCalls = 0
41+
s.stats = sync.Map{}
42+
atomic.StoreInt64(&s.callCount, 0)
43+
atomic.StoreInt64(&s.maxCalls, 0)
44+
}
45+
46+
func (s *Stats) MaxConcurrentCalls() int {
47+
return int(atomic.LoadInt64(&s.maxCalls))
4248
}
4349

4450
// testConn mimics a net.Conn to the peer.
@@ -50,7 +56,7 @@ type testLatencyConn struct {
5056
// NewTestConnWithReadLatency wraps a net.Conn with artificial read latency
5157
func NewTestConnWithReadLatency(conn net.Conn, readLatency time.Duration) net.Conn {
5258
return &testLatencyConn{
53-
Conn: conn,
59+
Conn: conn,
5460
readLatency: readLatency,
5561
}
5662
}
@@ -87,9 +93,9 @@ func NewUnresponsiveTestConn(delay time.Duration) net.Conn {
8793

8894
// Read reads from the in buffer.
8995
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)
96+
// Wait for delay to simulate network latency
97+
time.Sleep(c.delay)
98+
// Return empty data (success but zero bytes)
9399
return 0, nil
94100
}
95101

0 commit comments

Comments
 (0)