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>main
parent
986d60a094
commit
e92f4c6af8
@ -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) |
||||
} |
||||
@ -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") |
||||
} |
||||
} |
||||
Loading…
Reference in new issue