github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/state/raft/wait.go (about) 1 package raft 2 3 import ( 4 "fmt" 5 "sync" 6 ) 7 8 type waitItem struct { 9 // channel to wait up the waiter 10 ch chan interface{} 11 // callback which is called synchronously when the wait is triggered 12 cb func() 13 // callback which is called to cancel a waiter 14 cancel func() 15 } 16 17 type wait struct { 18 l sync.Mutex 19 m map[uint64]waitItem 20 } 21 22 func newWait() *wait { 23 return &wait{m: make(map[uint64]waitItem)} 24 } 25 26 func (w *wait) register(id uint64, cb func(), cancel func()) <-chan interface{} { 27 w.l.Lock() 28 defer w.l.Unlock() 29 _, ok := w.m[id] 30 if !ok { 31 ch := make(chan interface{}, 1) 32 w.m[id] = waitItem{ch: ch, cb: cb, cancel: cancel} 33 return ch 34 } 35 panic(fmt.Sprintf("duplicate id %x", id)) 36 } 37 38 func (w *wait) trigger(id uint64, x interface{}) bool { 39 w.l.Lock() 40 waitItem, ok := w.m[id] 41 delete(w.m, id) 42 w.l.Unlock() 43 if ok { 44 if waitItem.cb != nil { 45 waitItem.cb() 46 } 47 waitItem.ch <- x 48 return true 49 } 50 return false 51 } 52 53 func (w *wait) cancel(id uint64) { 54 w.l.Lock() 55 waitItem, ok := w.m[id] 56 delete(w.m, id) 57 w.l.Unlock() 58 if ok { 59 if waitItem.cancel != nil { 60 waitItem.cancel() 61 } 62 close(waitItem.ch) 63 } 64 } 65 66 func (w *wait) cancelAll() { 67 w.l.Lock() 68 defer w.l.Unlock() 69 70 for id, waitItem := range w.m { 71 delete(w.m, id) 72 if waitItem.cancel != nil { 73 waitItem.cancel() 74 } 75 close(waitItem.ch) 76 } 77 }