Skip to content

Instantly share code, notes, and snippets.

@groob
Created June 28, 2017 21:06
Show Gist options
  • Save groob/f4aa22ab6f4090ac24f94fe91e99688e to your computer and use it in GitHub Desktop.
Save groob/f4aa22ab6f4090ac24f94fe91e99688e to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"os"
"os/signal"
"time"
)
func main() {
// create the gate actor.
// it has a bidirectional channel so we can quit and wait for the closure to close.
g := &gate{
actionc: make(chan func()),
quitc: make(chan chan struct{}),
}
defer g.stop()
// start the actor loop
go g.loop()
// wait a bit to observe the loop ticker
time.Sleep(10 * time.Second)
g.actionc <- func() {
// send a closure on the action channel. it will be executed in the loop
// because it's managed by the select{} in the loop, we never get a race condition.
fmt.Println("hello from inside the loop")
fmt.Printf("I see that open is set to: %v\n", g.open)
g.open = true
fmt.Printf("Now I set it to true: %v\n", g.open)
time.Sleep(10 * time.Second)
fmt.Printf("It's still true: %v\n", g.open)
}
fmt.Println("I'll wait until CTRL + C to quit")
sig := make(chan os.Signal)
signal.Notify(sig, os.Interrupt)
<-sig
}
type gate struct {
actionc chan func()
quitc chan chan struct{}
// private field we care about working with
open bool
}
func (g *gate) loop() {
ticker := time.NewTicker(1 * time.Second).C
for {
select {
// if we get a closure on the channel execute it
case f := <-g.actionc:
f()
// every time the timer ticks, flip the value
case <-ticker:
g.open = !g.open
fmt.Printf("flipped value to %v\n", g.open)
// if we receive a value on the quit channel, terminate the loop.
case quit := <-g.quitc:
close(quit)
return
}
}
}
func (g *gate) stop() {
// to stop the loop, we pass a value on the quit channel and
// block until it returns
fmt.Println("closing gate actor loop")
quit := make(chan struct{})
g.quitc <- quit
<-quit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment