Skip to content

Commit 2553546

Browse files
committed
feat: libevm/sync.Pool[T] for type safety
1 parent 23b36e5 commit 2553546

File tree

3 files changed

+60
-8
lines changed

3 files changed

+60
-8
lines changed

core/state/trie_prefetcher.libevm.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
package state
1818

1919
import (
20-
"sync"
21-
2220
"github.com/ava-labs/libevm/common"
2321
"github.com/ava-labs/libevm/libevm/options"
22+
"github.com/ava-labs/libevm/libevm/sync"
2423
"github.com/ava-labs/libevm/log"
2524
)
2625

@@ -50,18 +49,18 @@ func WithWorkerPools(ctor func() WorkerPool) PrefetcherOption {
5049

5150
type subfetcherPool struct {
5251
workers WorkerPool
53-
tries sync.Pool
52+
tries sync.Pool[Trie]
5453
wg sync.WaitGroup
5554
}
5655

5756
// applyTo configures the [subfetcher] to use a [WorkerPool] if one was provided
5857
// with a [PrefetcherOption].
5958
func (c *prefetcherConfig) applyTo(sf *subfetcher) {
6059
sf.pool = &subfetcherPool{
61-
tries: sync.Pool{
60+
tries: sync.Pool[Trie]{
6261
// Although the workers may be shared between all subfetchers, each
6362
// MUST have its own Trie pool.
64-
New: func() any {
63+
New: func() Trie {
6564
return sf.db.CopyTrie(sf.trie)
6665
},
6766
},
@@ -94,7 +93,7 @@ func (p *subfetcherPool) wait() {
9493
func (p *subfetcherPool) execute(fn func(Trie)) {
9594
p.wg.Add(1)
9695
do := func() {
97-
t := p.tries.Get().(Trie)
96+
t := p.tries.Get()
9897
fn(t)
9998
p.tries.Put(t)
10099
p.wg.Done()

core/state/trie_prefetcher.libevm_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ import (
2020
"testing"
2121
"time"
2222

23-
"github.com/ava-labs/libevm/common"
2423
"github.com/stretchr/testify/assert"
24+
25+
"github.com/ava-labs/libevm/common"
2526
)
2627

2728
type synchronisingWorkerPool struct {
@@ -73,7 +74,7 @@ func TestStopPrefetcherWaitsOnWorkers(t *testing.T) {
7374

7475
<-pool.executed
7576
db.StopPrefetcher()
76-
// If this happens then either Execute() hadn't returned or Done() wasn't
77+
// If this errors then either Execute() hadn't returned or Done() wasn't
7778
// called.
7879
assert.Equalf(t, 2, pool.preconditionsToStopPrefetcher, "%T.StopPrefetcher() returned early", db)
7980
}

libevm/sync/sync.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2024 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
// Package sync extends the standard library's sync package.
18+
package sync
19+
20+
import "sync"
21+
22+
// Aliases of stdlib sync's types to avoid having to import it alongside this
23+
// package.
24+
type (
25+
Cond = sync.Cond
26+
Locker = sync.Locker
27+
Map = sync.Map
28+
Mutex = sync.Mutex
29+
Once = sync.Once
30+
RWMutex = sync.RWMutex
31+
WaitGroup = sync.WaitGroup
32+
)
33+
34+
// A Pool is a type-safe wrapper around [sync.Pool].
35+
type Pool[T any] struct {
36+
New func() T
37+
pool sync.Pool
38+
once Once
39+
}
40+
41+
// Get is equivalent to [sync.Pool.Get].
42+
func (p *Pool[T]) Get() T {
43+
p.once.Do(func() { // Do() guarantees at least once, not just only once
44+
p.pool.New = func() any { return p.New() }
45+
})
46+
return p.pool.Get().(T) //nolint:forcetypeassert
47+
}
48+
49+
// Put is equivalent to [sync.Pool.Put].
50+
func (p *Pool[T]) Put(t T) {
51+
p.pool.Put(t)
52+
}

0 commit comments

Comments
 (0)