mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
* chore: apply go fix modernizers from Go 1.26
automated refactoring: interface{} to any, slices.Contains,
and other idiomatic updates.
* feat(ci): add `go fix` check to Go analysis workflow
ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...`
produces any changes (similar to existing `go fmt` enforcement)
73 lines
1.3 KiB
Go
73 lines
1.3 KiB
Go
package repo
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
// OnlyOne tracks open Repos by arbitrary key and returns the already
|
|
// open one.
|
|
type OnlyOne struct {
|
|
mu sync.Mutex
|
|
active map[any]*ref
|
|
}
|
|
|
|
// Open a Repo identified by key. If Repo is not already open, the
|
|
// open function is called, and the result is remembered for further
|
|
// use.
|
|
//
|
|
// Key must be comparable, or Open will panic. Make sure to pick keys
|
|
// that are unique across different concrete Repo implementations,
|
|
// e.g. by creating a local type:
|
|
//
|
|
// type repoKey string
|
|
// r, err := o.Open(repoKey(path), open)
|
|
//
|
|
// Call Repo.Close when done.
|
|
func (o *OnlyOne) Open(key any, open func() (Repo, error)) (Repo, error) {
|
|
o.mu.Lock()
|
|
defer o.mu.Unlock()
|
|
if o.active == nil {
|
|
o.active = make(map[any]*ref)
|
|
}
|
|
|
|
item, found := o.active[key]
|
|
if !found {
|
|
repo, err := open()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
item = &ref{
|
|
parent: o,
|
|
key: key,
|
|
Repo: repo,
|
|
}
|
|
o.active[key] = item
|
|
}
|
|
item.refs++
|
|
return item, nil
|
|
}
|
|
|
|
type ref struct {
|
|
parent *OnlyOne
|
|
key any
|
|
refs uint32
|
|
Repo
|
|
}
|
|
|
|
var _ Repo = (*ref)(nil)
|
|
|
|
func (r *ref) Close() error {
|
|
r.parent.mu.Lock()
|
|
defer r.parent.mu.Unlock()
|
|
|
|
r.refs--
|
|
if r.refs > 0 {
|
|
// others are holding it open
|
|
return nil
|
|
}
|
|
|
|
// last one
|
|
delete(r.parent.active, r.key)
|
|
return r.Repo.Close()
|
|
}
|