Skip to content

Commit

Permalink
feat: add tryacquire function
Browse files Browse the repository at this point in the history
Adds a TryAcquire function, which will attempt to acquire a lock if slots are available. A boolean
indicating wether a slot was acquired is returned.

closes #6
  • Loading branch information
tlkamp committed Feb 24, 2025
1 parent 394f306 commit f8ec2da
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
16 changes: 16 additions & 0 deletions semaphore.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package semaphore
import (
"context"
"fmt"
"time"

"github.com/eapache/channels"
)
Expand Down Expand Up @@ -31,6 +32,21 @@ func (r *ResizableSemaphore) Acquire(ctx context.Context) error {
}
}

// TryAcquire will acquire a slot if any are available. A boolean indicating whether or not a slot was acquired is returned.
func (r *ResizableSemaphore) TryAcquire() bool {
// Configure a small timeout in case the final semaphore is acquired after the check and before
// this function acquires a semaphore.
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
defer cancel()
if r.Len() < r.Cap() {
if err := r.Acquire(ctx); err == nil {
return true
}
}

return false
}

// Release frees up a slot.
func (r *ResizableSemaphore) Release() {
<-r.ch.Out()
Expand Down
21 changes: 21 additions & 0 deletions semaphore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,24 @@ func TestAcquire(t *testing.T) {
a.ErrorIs(err, context.Canceled)
})
}

func TestTryAcquire(t *testing.T) {
a := assert.New(t)

t.Run("Successful", func(t *testing.T) {
r := New(1)

a.True(r.TryAcquire())
defer r.Release()
})

t.Run("Failure", func(t *testing.T) {
r := New(1)

ctx := context.Background()
a.NoError(r.Acquire(ctx))

defer r.Release()
a.False(r.TryAcquire())
})
}

0 comments on commit f8ec2da

Please sign in to comment.