Skip to content

Commit 00f8d47

Browse files
committed
refactor: Refactor pool to use upstream hashicorp/golang-lru package
1 parent 3d794c2 commit 00f8d47

File tree

3 files changed

+36
-67
lines changed

3 files changed

+36
-67
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ require (
2323
github.com/pmezard/go-difflib v1.0.0 // indirect
2424
gopkg.in/yaml.v3 v3.0.1 // indirect
2525
)
26+
27+
replace github.com/hashicorp/golang-lru/v2 => github.com/bodgit/golang-lru/v2 v2.0.0-20240402231653-73e2fffc225d

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
1919
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
2020
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
2121
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
22+
github.com/bodgit/golang-lru/v2 v2.0.0-20240402231653-73e2fffc225d h1:+VY4VHDvXKqMaaRcl7MUCs1YCIz7D4dC642ZClCGmXo=
23+
github.com/bodgit/golang-lru/v2 v2.0.0-20240402231653-73e2fffc225d/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
2224
github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
2325
github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs=
2426
github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
@@ -66,8 +68,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
6668
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
6769
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
6870
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
69-
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
70-
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
7171
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
7272
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
7373
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=

internal/pool/pool.go

Lines changed: 32 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package pool
22

33
import (
4-
"container/list"
54
"runtime"
65
"sort"
76
"sync"
87

98
"github.com/bodgit/sevenzip/internal/util"
9+
lru "github.com/hashicorp/golang-lru/v2"
1010
)
1111

1212
// Pooler is the interface implemented by a pool.
@@ -34,48 +34,54 @@ func (noopPool) Put(_ int64, rc util.SizeReadSeekCloser) (bool, error) {
3434
}
3535

3636
type pool struct {
37-
mutex sync.Mutex
38-
size int
39-
evictList *list.List
40-
items map[int64]*list.Element
41-
}
42-
43-
type entry struct {
44-
key int64
45-
value util.SizeReadSeekCloser
37+
mutex sync.Mutex
38+
errs chan error
39+
cache *lru.Cache[int64, util.SizeReadSeekCloser]
4640
}
4741

4842
// NewPool returns a Pooler that uses a LRU strategy to maintain a fixed pool
4943
// of util.SizeReadSeekCloser's keyed by their stream offset.
5044
func NewPool() (Pooler, error) {
45+
errs := make(chan error)
46+
47+
cache, err := lru.NewWithEvict[int64, util.SizeReadSeekCloser](
48+
runtime.NumCPU(),
49+
func(_ int64, value util.SizeReadSeekCloser) {
50+
if err := value.Close(); err != nil {
51+
errs <- err
52+
}
53+
})
54+
if err != nil {
55+
return nil, err
56+
}
57+
5158
return &pool{
52-
size: runtime.NumCPU(),
53-
evictList: list.New(),
54-
items: make(map[int64]*list.Element),
59+
errs: errs,
60+
cache: cache,
5561
}, nil
5662
}
5763

5864
func (p *pool) Get(offset int64) (util.SizeReadSeekCloser, bool) {
5965
p.mutex.Lock()
6066
defer p.mutex.Unlock()
6167

62-
if ent, ok := p.items[offset]; ok {
63-
_ = p.removeElement(ent, false)
68+
if reader, ok := p.cache.Get(offset); ok {
69+
_ = p.cache.RemoveWithoutEvict(offset)
6470

65-
return ent.Value.(*entry).value, true //nolint:forcetypeassert
71+
return reader, true
6672
}
6773

6874
// Sort keys in descending order
69-
keys := p.keys()
75+
keys := p.cache.Keys()
7076
sort.Slice(keys, func(i, j int) bool { return keys[i] > keys[j] })
7177

7278
for _, k := range keys {
7379
// First key less than offset is the closest
7480
if k < offset {
75-
ent := p.items[k]
76-
_ = p.removeElement(ent, false)
81+
reader, _ := p.cache.Get(k)
82+
_ = p.cache.RemoveWithoutEvict(k)
7783

78-
return ent.Value.(*entry).value, true //nolint:forcetypeassert
84+
return reader, true
7985
}
8086
}
8187

@@ -86,52 +92,13 @@ func (p *pool) Put(offset int64, rc util.SizeReadSeekCloser) (bool, error) {
8692
p.mutex.Lock()
8793
defer p.mutex.Unlock()
8894

89-
if _, ok := p.items[offset]; ok {
90-
return false, nil
91-
}
92-
93-
ent := &entry{offset, rc}
94-
entry := p.evictList.PushFront(ent)
95-
p.items[offset] = entry
96-
97-
var err error
98-
99-
evict := p.evictList.Len() > p.size
100-
if evict {
101-
err = p.removeOldest()
102-
}
103-
104-
return evict, err
105-
}
106-
107-
func (p *pool) keys() []int64 {
108-
keys := make([]int64, len(p.items))
109-
i := 0
110-
111-
for ent := p.evictList.Back(); ent != nil; ent = ent.Prev() {
112-
keys[i] = ent.Value.(*entry).key //nolint:forcetypeassert
113-
i++
114-
}
115-
116-
return keys
117-
}
118-
119-
func (p *pool) removeOldest() error {
120-
if ent := p.evictList.Back(); ent != nil {
121-
return p.removeElement(ent, true)
122-
}
123-
124-
return nil
125-
}
126-
127-
func (p *pool) removeElement(e *list.Element, cb bool) error {
128-
p.evictList.Remove(e)
129-
kv := e.Value.(*entry) //nolint:forcetypeassert
130-
delete(p.items, kv.key)
95+
_, ok := p.cache.ContainsOrAdd(offset, rc)
13196

132-
if cb {
133-
return kv.value.Close()
97+
select {
98+
case err := <-p.errs:
99+
return ok, err
100+
default:
134101
}
135102

136-
return nil
103+
return ok, nil
137104
}

0 commit comments

Comments
 (0)