github.com/aergoio/aergo@v1.3.1/p2p/p2putil/mutexpipe.go (about)

     1  /*
     2   * @file
     3   * @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package p2putil
     7  
     8  import (
     9  	"sync"
    10  	"sync/atomic"
    11  )
    12  
    13  type mutexPipe struct {
    14  	mutex *sync.Mutex
    15  
    16  	out chan interface{}
    17  
    18  	queue *PressableQueue
    19  	stop  int32
    20  
    21  	listener PipeEventListener
    22  }
    23  
    24  // newMutexPipe create pipe to output channel out
    25  func newMutexPipe(bufSize int, listener PipeEventListener) *mutexPipe {
    26  	if listener == nil {
    27  		listener = &StatListener{}
    28  	}
    29  	c := &mutexPipe{
    30  		mutex: new(sync.Mutex),
    31  		out:   make(chan interface{}, 1),
    32  
    33  		queue: NewPressableQueue(bufSize),
    34  
    35  		listener: listener,
    36  	}
    37  
    38  	return c
    39  }
    40  
    41  func (c *mutexPipe) Put(mo interface{}) bool {
    42  	// stop is set after this pipe is closed
    43  	if atomic.LoadInt32(&c.stop) != 0 {
    44  		return false
    45  	}
    46  	c.mutex.Lock()
    47  	defer c.mutex.Unlock()
    48  	c.listener.OnIn(mo)
    49  	if len(c.out) == 0 {
    50  		if c.queue.Empty() {
    51  			c.pushToOut(mo)
    52  		} else {
    53  			c.pushToOut(c.queue.Poll())
    54  			c.queue.Offer(mo) // this offer always return true
    55  		}
    56  	} else {
    57  		if dropped := c.queue.Press(mo); dropped != nil {
    58  			c.listener.OnDrop(dropped)
    59  		}
    60  	}
    61  	return true
    62  }
    63  
    64  func (c *mutexPipe) Out() <-chan interface{} {
    65  	return c.out
    66  }
    67  
    68  func (c *mutexPipe) Done() {
    69  	c.mutex.Lock()
    70  	defer c.mutex.Unlock()
    71  	if len(c.out) == 0 && !c.queue.Empty() {
    72  		c.pushToOut(c.queue.Poll())
    73  	}
    74  }
    75  
    76  func (c *mutexPipe) Open() {
    77  	atomic.StoreInt32(&c.stop, 0)
    78  }
    79  func (c *mutexPipe) Close() {
    80  	atomic.StoreInt32(&c.stop, 1)
    81  }
    82  
    83  func (c *mutexPipe) pushToOut(e interface{}) {
    84  	c.out <- e
    85  	c.listener.OnOut(e)
    86  }