Last active
May 15, 2020 09:54
-
-
Save gtors/bee5f5b3f9c060fb2379e3016537529e to your computer and use it in GitHub Desktop.
Go dynamic resizable worker pool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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