Last active
May 3, 2018 00:00
-
-
Save as/b490b8809a734b20a0bbede87f2d4836 to your computer and use it in GitHub Desktop.
This file contains 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 "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