Skip to content

Instantly share code, notes, and snippets.

Created January 28, 2013 14:32
Show Gist options
  • Save samthor/4655953 to your computer and use it in GitHub Desktop.
Save samthor/4655953 to your computer and use it in GitHub Desktop.
CastGroup, something that lets listeners subscribe to broadcast events. Built for the garage door; will be used to support hanging GETs on some event.
package main
import (
func main() {
c := NewCastGroup()
go func() {
log.Printf("golang 1")
log.Printf("1.1 go: %v", c.Wait())
log.Printf("1.2 go: %v", c.Wait())
go func() {
log.Printf("golang 2")
log.Printf("2.1 go: %v", c.Wait())
go func() {
log.Printf("golang 3")
log.Printf("3.1 go: %v", c.Wait())
log.Printf("3.2 go: %v", c.Wait())
log.Printf("3.3 go: %v", c.Wait())
log.Printf("3.4 go: %v", c.Wait())
log.Printf("3.5 go: %v", c.Wait())
log.Printf("3.6 go: %v", c.Wait())
count := 0
for {
time.Sleep(1 * time.Second)
log.Printf("done event %d", count)
type CastGroup struct {
result chan interface{}
ch chan *event
type event struct {
wait chan bool
result interface{}
// Done signals all holders of the current event that the event is done; providing the
// given value in the event.
func (c *CastGroup) Done(v interface{}) {
// the passed event is overloaded with the result of the previous event...
c.result <- v
// Wait blocks until the current event is done, providing its result.
func (c *CastGroup) Wait() interface{} {
current := <
_, ok := <-current.wait
if ok {
panic("chan should only ever be closed")
return current.result
func NewCastGroup() *CastGroup {
c := &CastGroup{make(chan interface{}), make(chan *event)}
go func() {
var current *event
for {
select {
case result := <-c.result:
if current != nil {
current.result = result
} else if result != nil {
panic("first update must be nil")
current = &event{make(chan bool), nil}
case <- current:
// Wait() is being invoked; pass the current event.
return c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment