Skip to content

Instantly share code, notes, and snippets.

@gtors
Last active May 15, 2020 09:54
Show Gist options
  • Save gtors/bee5f5b3f9c060fb2379e3016537529e to your computer and use it in GitHub Desktop.
Save gtors/bee5f5b3f9c060fb2379e3016537529e to your computer and use it in GitHub Desktop.
Go dynamic resizable worker pool
package main
import (
"sync"
"time"
)
type WorkerPool struct {
sync.Mutex
sync.WaitGroup
workers uint
terminated bool
die chan bool
tasks chan func()
}
func (wp *WorkerPool) Resize(sz uint) {
wp.Lock()
defer wp.Unlock()
if wp.terminated {
return
}
if sz > wp.workers {
toSpawn := sz - wp.workers
for i := uint(0); i < toSpawn; i++ {
wp.spawnWorker()
}
} else {
toDie := wp.workers - sz
for i := uint(0); i < toDie; i++ {
wp.die <- true
}
}
wp.workers = sz
}
func (wp *WorkerPool) SendTask(f func()) {
if wp.terminated {
return
}
wp.tasks <- f
}
func (wp *WorkerPool) Terminate() {
wp.Lock()
defer wp.Unlock()
if wp.terminated {
return
}
wp.terminated = true
close(wp.die)
}
func (wp *WorkerPool) spawnWorker() {
if wp.terminated {
return
}
wp.Add(1)
go func(tasks <-chan func(), die <-chan bool) {
defer wp.Done()
for {
select {
case <-die:
return
case task := <- tasks:
task()
}
}
}(wp.tasks, wp.die)
}
func NewWorkerPool(sz uint) *WorkerPool {
wp := new(WorkerPool)
wp.tasks = make(chan func(), 1)
wp.die = make(chan bool, 1)
wp.workers = uint(0)
wp.Resize(sz)
return wp
}
func sendHelloTasks(wp *WorkerPool) {
for i := 0; i < 5; i++ {
wp.SendTask(func() {
println("Say hello", i)
})
}
}
func main() {
wp := NewWorkerPool(5)
println("Сообщения будут в произвольном порядке, т.к. 5ть воркеров")
sendHelloTasks(wp)
time.Sleep(100 * time.Millisecond)
wp.Resize(1)
println("Сообщения будут последовательно, т.к. 1 воркер")
sendHelloTasks(wp)
wp.Terminate()
wp.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment