diff --git a/syncs/syncs.go b/syncs/syncs.go index e85b474c9..3b37bca08 100644 --- a/syncs/syncs.go +++ b/syncs/syncs.go @@ -201,6 +201,13 @@ func NewSemaphore(n int) Semaphore { 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. func (s Semaphore) Acquire() { s.c <- struct{}{} diff --git a/syncs/syncs_test.go b/syncs/syncs_test.go index d99c3d1a9..a546b8d0a 100644 --- a/syncs/syncs_test.go +++ b/syncs/syncs_test.go @@ -162,10 +162,20 @@ func TestClosedChan(t *testing.T) { func TestSemaphore(t *testing.T) { 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() + assertLen(1) if !s.TryAcquire() { t.Fatal("want true") } + assertLen(2) if s.TryAcquire() { t.Fatal("want false") } @@ -175,11 +185,15 @@ func TestSemaphore(t *testing.T) { t.Fatal("want false") } s.Release() + assertLen(1) if !s.AcquireContext(context.Background()) { t.Fatal("want true") } + assertLen(2) s.Release() + assertLen(1) s.Release() + assertLen(0) } func TestMap(t *testing.T) {