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  }