syncs: add Semaphore.Len (#16981)

The Len reports the number of acquired tokens for metrics.

Updates tailscale/corp#31252

Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
Joe Tsai 2025-08-29 10:33:14 -07:00 committed by GitHub
parent 1a98943204
commit 7cbcc10eb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 0 deletions

View File

@ -201,6 +201,13 @@ func NewSemaphore(n int) Semaphore {
return Semaphore{c: make(chan struct{}, n)} return Semaphore{c: make(chan struct{}, n)}
} }
// Len reports the number of in-flight acquisitions.
// It is incremented whenever the semaphore is acquired.
// It is decremented whenever the semaphore is released.
func (s Semaphore) Len() int {
return len(s.c)
}
// Acquire blocks until a resource is acquired. // Acquire blocks until a resource is acquired.
func (s Semaphore) Acquire() { func (s Semaphore) Acquire() {
s.c <- struct{}{} s.c <- struct{}{}

View File

@ -162,10 +162,20 @@ func TestClosedChan(t *testing.T) {
func TestSemaphore(t *testing.T) { func TestSemaphore(t *testing.T) {
s := NewSemaphore(2) s := NewSemaphore(2)
assertLen := func(want int) {
t.Helper()
if got := s.Len(); got != want {
t.Fatalf("Len = %d, want %d", got, want)
}
}
assertLen(0)
s.Acquire() s.Acquire()
assertLen(1)
if !s.TryAcquire() { if !s.TryAcquire() {
t.Fatal("want true") t.Fatal("want true")
} }
assertLen(2)
if s.TryAcquire() { if s.TryAcquire() {
t.Fatal("want false") t.Fatal("want false")
} }
@ -175,11 +185,15 @@ func TestSemaphore(t *testing.T) {
t.Fatal("want false") t.Fatal("want false")
} }
s.Release() s.Release()
assertLen(1)
if !s.AcquireContext(context.Background()) { if !s.AcquireContext(context.Background()) {
t.Fatal("want true") t.Fatal("want true")
} }
assertLen(2)
s.Release() s.Release()
assertLen(1)
s.Release() s.Release()
assertLen(0)
} }
func TestMap(t *testing.T) { func TestMap(t *testing.T) {