syncs: add generic Pool (#12759)

Pool is a type-safe wrapper over sync.Pool.

Updates tailscale/corp#11038
Updates #cleanup

Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
Joe Tsai 2024-07-10 09:39:52 -07:00 committed by GitHub
parent 986d60a094
commit e92f4c6af8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 0 deletions

31
syncs/pool.go Normal file
View File

@ -0,0 +1,31 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package syncs
import "sync"
// Pool is the generic version of [sync.Pool].
type Pool[T any] struct {
pool sync.Pool
// New optionally specifies a function to generate
// a value when Get would otherwise return the zero value of T.
// It may not be changed concurrently with calls to Get.
New func() T
}
// Get selects an arbitrary item from the Pool, removes it from the Pool,
// and returns it to the caller. See [sync.Pool.Get].
func (p *Pool[T]) Get() T {
x, ok := p.pool.Get().(T)
if !ok && p.New != nil {
x = p.New()
}
return x
}
// Put adds x to the pool.
func (p *Pool[T]) Put(x T) {
p.pool.Put(x)
}

30
syncs/pool_test.go Normal file
View File

@ -0,0 +1,30 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package syncs
import "testing"
func TestPool(t *testing.T) {
var pool Pool[string]
s := pool.Get() // should not panic
if s != "" {
t.Fatalf("got %q, want %q", s, "")
}
pool.New = func() string { return "new" }
s = pool.Get()
if s != "new" {
t.Fatalf("got %q, want %q", s, "new")
}
var found bool
for range 1000 {
pool.Put("something")
found = pool.Get() == "something"
if found {
break
}
}
if !found {
t.Fatalf("unable to get any value put in the pool")
}
}