aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/cli/internal/util/semaphore.go
diff options
context:
space:
mode:
Diffstat (limited to 'cli/internal/util/semaphore.go')
-rw-r--r--cli/internal/util/semaphore.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/cli/internal/util/semaphore.go b/cli/internal/util/semaphore.go
new file mode 100644
index 0000000..ef29df0
--- /dev/null
+++ b/cli/internal/util/semaphore.go
@@ -0,0 +1,43 @@
+package util
+
+// Semaphore is a wrapper around a channel to provide
+// utility methods to clarify that we are treating the
+// channel as a semaphore
+type Semaphore chan struct{}
+
+// NewSemaphore creates a semaphore that allows up
+// to a given limit of simultaneous acquisitions
+func NewSemaphore(n int) Semaphore {
+ if n <= 0 {
+ panic("semaphore with limit <=0")
+ }
+ ch := make(chan struct{}, n)
+ return Semaphore(ch)
+}
+
+// Acquire is used to acquire an available slot.
+// Blocks until available.
+func (s Semaphore) Acquire() {
+ s <- struct{}{}
+}
+
+// TryAcquire is used to do a non-blocking acquire.
+// Returns a bool indicating success
+func (s Semaphore) TryAcquire() bool {
+ select {
+ case s <- struct{}{}:
+ return true
+ default:
+ return false
+ }
+}
+
+// Release is used to return a slot. Acquire must
+// be called as a pre-condition.
+func (s Semaphore) Release() {
+ select {
+ case <-s:
+ default:
+ panic("release without an acquire")
+ }
+}