a tiny concurrency manager for go
coma makes sure your program doesn't get overwhelmed with goroutines and fall into a coma.
- limits how many goroutines run at once
- waits until all of them are done
- is simple
- works
go get github.com/zlatej/comagate := coma.New(5) // at most 5 goroutines at a time
for _, task := range tasks {
// blocks until a slot is free and acquires it
if err := gate.AcquireContext(ctx); err != nil {
// error means either the context is done or Drain has been called
return
}
go func() {
defer gate.Release() // releases slot
process(task)
}()
}
fmt.Printf("currently holding %d slots\n", gate.Held())
gate.Drain() // blocks until all slots are releasedno context? use gate.Acquire() instead
if you want to close the Gate from one place, but still wait until all tasks are done in a different place.
gate := coma.New(5) // at most 5 goroutines at a time
go func() {
<-sigint
gate.Close() // close from remote call
}()
for {
task := getTask()
if err := gate.Acquire(); err != nil { // returns ErrClosed after gate.Close()
break
}
go func() {
defer gate.Release()
process(task)
}()
}
gate.Drain() // already closed, just wait until all slots are releasedNewtreats amaxof less than 1 as 1.Closeis terminal: once called, the Gate cannot be reused,Acquire/AcquireContextwill returnErrClosed.Drainbehaves likeClosebut then blocks until all slots are released.DrainandClosecan be combined and can safely be called any number of times, including concurrently from multiple goroutines.- every successful
Acquire/AcquireContextmust be matched by exactly oneRelease. An unmatchedReleasepanics when no slot is held.