github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/structs/funcs.go (about) 1 package structs 2 3 import ( 4 "sync" 5 6 "github.com/hashicorp/nomad/nomad/structs" 7 ) 8 9 // AllocBroadcaster implements an allocation broadcast channel. 10 // The zero value is a usable unbuffered channel. 11 type AllocBroadcaster struct { 12 m sync.Mutex 13 listeners map[int]chan<- *structs.Allocation // lazy init 14 nextId int 15 capacity int 16 closed bool 17 } 18 19 // NewAllocBroadcaster returns a new AllocBroadcaster with the given capacity (0 means unbuffered). 20 func NewAllocBroadcaster(n int) *AllocBroadcaster { 21 return &AllocBroadcaster{capacity: n} 22 } 23 24 // AllocListener implements a listening endpoint for an allocation broadcast channel. 25 type AllocListener struct { 26 // Ch receives the broadcast messages. 27 Ch <-chan *structs.Allocation 28 b *AllocBroadcaster 29 id int 30 } 31 32 // Send broadcasts a message to the channel. Send returns whether the message 33 // was sent to all channels. 34 func (b *AllocBroadcaster) Send(v *structs.Allocation) bool { 35 b.m.Lock() 36 defer b.m.Unlock() 37 if b.closed { 38 return false 39 } 40 sent := true 41 for _, l := range b.listeners { 42 select { 43 case l <- v: 44 default: 45 sent = false 46 } 47 } 48 49 return sent 50 } 51 52 // Close closes the channel, disabling the sending of further messages. 53 func (b *AllocBroadcaster) Close() { 54 b.m.Lock() 55 defer b.m.Unlock() 56 if b.closed { 57 return 58 } 59 60 b.closed = true 61 for _, l := range b.listeners { 62 close(l) 63 } 64 } 65 66 // Listen returns a Listener for the broadcast channel. 67 func (b *AllocBroadcaster) Listen() *AllocListener { 68 b.m.Lock() 69 defer b.m.Unlock() 70 if b.listeners == nil { 71 b.listeners = make(map[int]chan<- *structs.Allocation) 72 } 73 for b.listeners[b.nextId] != nil { 74 b.nextId++ 75 } 76 ch := make(chan *structs.Allocation, b.capacity) 77 if b.closed { 78 close(ch) 79 } 80 b.listeners[b.nextId] = ch 81 return &AllocListener{ch, b, b.nextId} 82 } 83 84 // Close closes the Listener, disabling the receival of further messages. 85 func (l *AllocListener) Close() { 86 l.b.m.Lock() 87 defer l.b.m.Unlock() 88 delete(l.b.listeners, l.id) 89 }