Skip to content

Instantly share code, notes, and snippets.

@eriknelson
Created November 16, 2016 19:01
Show Gist options
  • Save eriknelson/e158e04e9f54eecd279b65a1116c47ab to your computer and use it in GitHub Desktop.
Save eriknelson/e158e04e9f54eecd279b65a1116c47ab to your computer and use it in GitHub Desktop.
Async go workers
package main
import (
"fmt"
"math/rand"
"runtime"
"sync"
"time"
)
const (
INITIALIZING = iota
RUNNING = iota
FINALIZING = iota
FINISHED = iota
)
var (
stateText map[int]string
wg sync.WaitGroup
)
type WorkMachine struct {
name string
stateGraph map[int]int
currentState int
stateWeights map[int]int
totalWeight int
totalTicks int
stateTicks int
totalProgress float32
stateProgress float32
}
func NewWorkMachine(name string) WorkMachine {
stateGraph := map[int]int{
INITIALIZING: RUNNING,
RUNNING: FINALIZING,
FINALIZING: FINISHED,
}
stateWeights := make(map[int]int)
shortWeight := random(3, 7)
longWeight := random(7, 12)
totalWeight := shortWeight*2 + longWeight
stateWeights[INITIALIZING] = shortWeight
stateWeights[RUNNING] = longWeight
stateWeights[FINALIZING] = shortWeight
return WorkMachine{
name: name,
stateWeights: stateWeights,
stateGraph: stateGraph,
totalWeight: totalWeight,
}
}
func (m *WorkMachine) Tick() {
// check to see if we need to transition to the next state
if m.stateWeights[m.currentState] == m.stateTicks {
m.stateTicks = 0 // Reset state ticker
m.currentState = m.stateGraph[m.currentState] // Transition to next state
}
m.totalTicks++
m.stateTicks++
m.totalProgress = float32(m.totalTicks) / float32(m.totalWeight)
m.stateProgress = float32(m.stateTicks) / float32(m.stateWeights[m.currentState])
}
func (m *WorkMachine) Report() {
fmt.Printf("%s -> State: %s, State Progress: %.2f, Total Progress: %.2f \n",
m.name, stateText[m.currentState], m.stateProgress, m.totalProgress)
}
func init() {
runtime.GOMAXPROCS(2)
stateText = map[int]string{
INITIALIZING: "Initializing",
RUNNING: "Running",
FINALIZING: "Finalizing",
FINISHED: "Finished",
}
rand.Seed(time.Now().UnixNano())
}
func main() {
wg.Add(2)
fmt.Println("Starting machines!")
runMachine("FOO")
runMachine("BAR")
fmt.Println("Waiting for the machines to finish up!")
wg.Wait()
fmt.Println("All finished!")
}
func runMachine(name string) {
machine := NewWorkMachine(name)
go func() {
defer wg.Done()
fmt.Printf("total weight -> %d\n", machine.totalWeight)
fmt.Println(machine.stateWeights)
for {
if machine.currentState == FINISHED {
break
}
machine.Tick()
if machine.currentState != FINISHED {
machine.Report()
}
}
fmt.Printf("Finished -> %d, %d, %.2f\n",
machine.currentState,
machine.totalTicks,
machine.totalProgress,
)
}()
}
func random(min, max int) int {
return rand.Intn(max-min) + min
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment