Skip to content

Instantly share code, notes, and snippets.

@as
Last active May 3, 2018 00:00
Show Gist options
  • Save as/b490b8809a734b20a0bbede87f2d4836 to your computer and use it in GitHub Desktop.
Save as/b490b8809a734b20a0bbede87f2d4836 to your computer and use it in GitHub Desktop.
package main
import "time"
//
// [ producer ] ---------- [ scheduler ] ----------- [ consumer ]
// | |
// [ cpu ]
// [ cpu ]
// [ cpu ]
//
// Q1: Where is the scheduler?
// Q2: Validate this with spin
// Q3: Replace all channel operations with locks, compare.
// Q4: Replace the coord channel with a waitgroup. Was it worth it?
// Q5: Modify the code so that the second CPU to exit does the teardown, is that safe?
type work int
type status int
type cpu struct {
i chan work
o chan work
e chan bool
coord chan bool
}
func (c *cpu) close() {
select {
case last := <-c.coord:
if last {
close(c.coord)
close(c.e)
close(c.o)
}
default:
}
}
func (c *cpu) execute(w work, more bool) (bool) {
if !more {
return false
}
select {
case <-c.e:
return false
default:
}
{
//
// This is what this cpu considers work
//
time.Sleep(time.Second / 73)
}
c.o <- w
return true
}
func Run(c *cpu) {
defer c.close()
for {
select {
case <-c.e:
return
case w, more := <-c.i:
if !c.execute(w, more){
return
}
}
}
}
func main() {
const(
NCpu = 3
NItems = 127
deadline = time.Second
tickrate = time.Second/23
)
I := make(chan work, NCpu)
O := make(chan work)
E := make(chan bool)
// Set up a channel where the last valid read triggers
// a teardown by returning true.
coord := make(chan bool, NCpu)
for i := 0; i < NCpu-1; i++ {
coord <- false
}
coord <- true
// Processor - recieve work, complete work, output work
for i := 0; i < cap(I); i++ {
go Run(&cpu{I, O, E, coord})
}
// Producer - create work and send it in
go func() {
for i := 0; i < NItems; i++ {
I <- work(i)
println("producer:", i)
}
close(I) // Producer closes input chan
}()
// Consumer - recieves completed work from the cpu group
dead := time.After(deadline)
clock:= time.NewTicker(tickrate)
Loop:
for {
select {
case <-clock.C:
println("consumer: still alive")
case <-dead:
println("consumer: deadline: disconnect")
break Loop
case w, more := <-O:
if !more {
println("consumer: done")
break Loop
}
println("consumer: got", w)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment