github.com/haraldrudell/parl@v0.4.176/nb-chan-data-wait-ch.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package parl 7 8 // updateDataAvailable obtains a properly configured dataWaitCh 9 // - used by DataWaitCh to obtain the channel 10 // - by thread after sending an item 11 // - by thread on detecting CloseNow 12 func (n *NBChan[T]) updateDataAvailable() (dataCh chan struct{}) { 13 if n.closableChan.IsClosed() { 14 // after underlying channel close, a triggered channel is returned 15 return n.setDataAvailableAfterClose() 16 } 17 // return channel from current state 18 return n.setDataAvailable(n.unsentCount.Load() > 0) 19 } 20 21 // setDataAvailableAfterClose ensures dataWaitCh is initialized and triggered 22 // - consumers waiting for dataWaitCh will then not block 23 // - used at end of Close, CloseNow and deferred close by thread 24 func (n *NBChan[T]) setDataAvailableAfterClose() (dataCh chan struct{}) { 25 return n.setDataAvailable(true) 26 } 27 28 // setDataAvailable configured dataWaitCh to be aligned with isAvailable 29 // - updated by Get Send SendMany 30 // - also indirect by updateDataAvailable and setDataAvailableAfterClose 31 func (n *NBChan[T]) setDataAvailable(isAvailable bool) (dataCh chan struct{}) { 32 if chp := n.dataWaitCh.Load(); chp != nil && n.isDataAvailable.Load() == isAvailable { 33 dataCh = *chp 34 return // initialized and in correct state return: noop 35 } 36 n.availableLock.Lock() 37 defer n.availableLock.Unlock() 38 39 // not yet initialized case 40 var chp = n.dataWaitCh.Load() 41 if chp == nil { 42 dataCh = make(chan struct{}) 43 if isAvailable { 44 close(dataCh) 45 } 46 n.dataWaitCh.Store(&dataCh) 47 n.isDataAvailable.Store(isAvailable) 48 return // channel initialized and state set return 49 } 50 51 // is state correct? 52 dataCh = *chp 53 if n.isDataAvailable.Load() == isAvailable { 54 return // channel was initialized and state was correct return 55 } 56 57 // should channel be closed: if data is available 58 if isAvailable { 59 close(*chp) 60 n.isDataAvailable.Store(true) 61 return // channel closed andn state updated return 62 } 63 64 // replace with open channel: data is not available 65 dataCh = make(chan struct{}) 66 n.dataWaitCh.Store(&dataCh) 67 n.isDataAvailable.Store(false) 68 return // new open channel stored and state updated return 69 }