Skip to content

Instantly share code, notes, and snippets.

@paddycarver
Created January 29, 2016 08:28
Show Gist options
  • Save paddycarver/e2589d969025bda892bd to your computer and use it in GitHub Desktop.
Save paddycarver/e2589d969025bda892bd to your computer and use it in GitHub Desktop.
Whippersnapper.com concurrency exercises
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func useComputer(tourists chan int, done chan struct{}) {
for tourist := range tourists {
fmt.Println("Tourist", tourist, "is online.")
duration := time.Duration(rand.Intn(15)) * time.Second
time.Sleep(duration)
fmt.Printf("Tourist %d is done, having spent %d minutes online.\n", tourist, duration/time.Second)
}
close(done)
}
func waitForComputer(tourists chan int, tourist int, wg *sync.WaitGroup) {
select {
case tourists <- tourist:
default:
fmt.Println("Tourist", tourist, "waiting for turn.")
}
tourists <- tourist
wg.Done()
}
func main() {
rand.Seed(time.Now().Unix())
tourists := make(chan int)
comp1 := make(chan struct{})
comp2 := make(chan struct{})
comp3 := make(chan struct{})
comp4 := make(chan struct{})
comp5 := make(chan struct{})
comp6 := make(chan struct{})
comp7 := make(chan struct{})
comp8 := make(chan struct{})
go useComputer(tourists, comp1)
go useComputer(tourists, comp2)
go useComputer(tourists, comp3)
go useComputer(tourists, comp4)
go useComputer(tourists, comp5)
go useComputer(tourists, comp6)
go useComputer(tourists, comp7)
go useComputer(tourists, comp8)
var wg sync.WaitGroup
for i := 1; i <= 25; i++ {
wg.Add(1)
go waitForComputer(tourists, i, &wg)
}
wg.Wait()
close(tourists)
<-comp1
<-comp2
<-comp3
<-comp4
<-comp5
<-comp6
<-comp7
<-comp8
fmt.Println("The place is empty, let's close up and go to the beach!")
}
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func merge(chans ...<-chan string) <-chan string {
var wg sync.WaitGroup
out := make(chan string)
output := func(c <-chan string) {
for n := range c {
out <- n
}
wg.Done()
}
wg.Add(len(chans))
for _, c := range chans {
go output(c)
}
go func() {
wg.Wait()
close(out)
}()
return out
}
func serveFood(name string, platter chan string) {
numFood := rand.Intn(5) + 5
for i := 0; i < numFood; i++ {
platter <- name
}
close(platter)
}
func eat(name string, table <-chan string, plate chan struct{}) {
for morsel := range table {
fmt.Println(name, "is enjoying some", morsel)
delay := time.Duration(rand.Intn(15)) * time.Second
time.Sleep(delay)
}
close(plate)
}
func main() {
rand.Seed(time.Now().Unix())
fmt.Println("Bon appétit")
chorizo := make(chan string)
chopitos := make(chan string)
pimientos := make(chan string)
croquetas := make(chan string)
patatas := make(chan string)
go serveFood("chorizo", chorizo)
go serveFood("chopitos", chopitos)
go serveFood("pimientos de padrón", pimientos)
go serveFood("croquetas", croquetas)
go serveFood("patatas bravas", patatas)
table := merge(chorizo, chopitos, pimientos, croquetas, patatas)
alice := make(chan struct{})
bob := make(chan struct{})
charlie := make(chan struct{})
dave := make(chan struct{})
go eat("Alice", table, alice)
go eat("Bob", table, bob)
go eat("Charlie", table, charlie)
go eat("Dave", table, dave)
<-alice
<-bob
<-charlie
<-dave
fmt.Println("That was delicious!")
}
package main
import (
"fmt"
"math/rand"
"time"
)
func getReady(name string, done chan time.Duration) {
fmt.Printf("%s started getting ready\n", name)
timeGettingReady := time.Second * time.Duration(rand.Intn(30)+60)
time.Sleep(timeGettingReady)
done <- timeGettingReady
}
func resolveReady(aliceDur, bobDur chan time.Duration) {
select {
case dur := <-aliceDur:
fmt.Printf("Alice spent %d seconds getting ready\n", dur/time.Second)
case dur := <-bobDur:
fmt.Printf("Bob spent %d seconds getting ready\n", dur/time.Second)
}
}
func armAlarm(done chan struct{}) {
fmt.Println("Alarm is counting down.")
time.Sleep(60 * time.Second)
fmt.Println("Alarm is armed.")
close(done)
}
func putShoesOn(name string, done chan time.Duration) {
fmt.Printf("%s started putting on shoes\n", name)
timePuttingOnShoes := time.Second * time.Duration(rand.Intn(10)+35)
time.Sleep(timePuttingOnShoes)
done <- timePuttingOnShoes
}
func resolveShoes(aliceShoes, bobShoes chan time.Duration) {
select {
case dur := <-aliceShoes:
fmt.Printf("Alice spent %d seconds putting on shoes\n", dur/time.Second)
case dur := <-bobShoes:
fmt.Printf("Bob spent %d seconds putting on shoes\n", dur/time.Second)
}
}
func main() {
rand.Seed(time.Now().Unix())
fmt.Println("Let's go for a walk!")
aliceReady, bobReady := make(chan time.Duration), make(chan time.Duration)
go getReady("Alice", aliceReady)
go getReady("Bob", bobReady)
// we want both to be ready, but don't care the order
resolveReady(aliceReady, bobReady)
resolveReady(aliceReady, bobReady)
fmt.Println("Arming alarm.")
alarmDone := make(chan struct{})
go armAlarm(alarmDone)
aliceShoes, bobShoes := make(chan time.Duration), make(chan time.Duration)
go putShoesOn("Alice", aliceShoes)
go putShoesOn("Bob", bobShoes)
resolveShoes(aliceShoes, bobShoes)
resolveShoes(aliceShoes, bobShoes)
fmt.Println("Exiting and locking the door.")
<-alarmDone
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment