Skip to content

Instantly share code, notes, and snippets.

@Fornax96
Last active May 4, 2020 09:04
Show Gist options
  • Save Fornax96/8c57dcce317a73afc320da019d827eda to your computer and use it in GitHub Desktop.
Save Fornax96/8c57dcce317a73afc320da019d827eda to your computer and use it in GitHub Desktop.
The execution limiter limits the execution of a certain task to X concurrent goroutines. This can be used to prevent servers from running out of memory
package util
// ExecutionLimiter is a utility which limits the concurrent execution of a
// function. When it is initialized it creates a channel with x capacity and
// fills it with x booleans. Every time the Lock() function is called a bool is
// removed from the channel. When the channel is empty the function will block
// until the Unlock function is called, which puts a new bool into the channel.
type ExecutionLimiter struct {
channel chan bool
}
// NewExecutionLimiter creates a new Exection Limiter. The numThreads parameter
// is how many threads can concurrently execute the function
func NewExecutionLimiter(numThreads int) (el *ExecutionLimiter) {
el = &ExecutionLimiter{
channel: make(chan bool, numThreads),
}
// Fill the channel with bools. Each boolean essentially acts as an
// execution slot. When the channel is empty the Lock function will block
// until a new bool is fed into the channel through Unlock
for i := 0; i < numThreads; i++ {
el.channel <- true
}
return el
}
// Stop the ExecutionLimiter. This destroys the channel. Calling Unlock after
// Stop will panic
func (el *ExecutionLimiter) Stop() { close(el.channel) }
// Lock the ExecutionLimiter
func (el *ExecutionLimiter) Lock() { <-el.channel }
// Unlock the ExecutionLimiter
func (el *ExecutionLimiter) Unlock() { el.channel <- true }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment