github.com/jmigpin/editor@v1.6.0/util/chanutil/chanq.go (about)

     1  package chanutil
     2  
     3  import (
     4  	"container/list"
     5  )
     6  
     7  // Flexible channel queue (no fixed length). Note: consider using syncutil.* instead.
     8  type ChanQ struct {
     9  	q       list.List
    10  	in, out chan interface{}
    11  }
    12  
    13  func NewChanQ(inSize, outSize int) *ChanQ {
    14  	ch := &ChanQ{}
    15  	ch.in = make(chan interface{}, inSize)
    16  	ch.out = make(chan interface{}, outSize)
    17  	go ch.loop()
    18  	return ch
    19  }
    20  
    21  func (ch *ChanQ) In() chan<- interface{} {
    22  	return ch.in
    23  }
    24  
    25  func (ch *ChanQ) Out() <-chan interface{} {
    26  	return ch.out
    27  }
    28  
    29  func (ch *ChanQ) loop() {
    30  	var next interface{}
    31  	var out chan<- interface{}
    32  	for {
    33  		select {
    34  		case v := <-ch.in:
    35  			if next == nil {
    36  				next = v
    37  				out = ch.out
    38  			} else {
    39  				ch.q.PushBack(v)
    40  			}
    41  		case out <- next:
    42  			elem := ch.q.Front()
    43  			if elem == nil {
    44  				next = nil
    45  				out = nil
    46  			} else {
    47  				next = elem.Value
    48  				out = ch.out
    49  				ch.q.Remove(elem)
    50  			}
    51  		}
    52  	}
    53  }