github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/peer/queue/sync.go (about)

     1  package queue
     2  
     3  import (
     4  	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
     5  
     6  	peer "github.com/jbenet/go-ipfs/peer"
     7  )
     8  
     9  // ChanQueue makes any PeerQueue synchronizable through channels.
    10  type ChanQueue struct {
    11  	Queue   PeerQueue
    12  	EnqChan chan<- peer.Peer
    13  	DeqChan <-chan peer.Peer
    14  }
    15  
    16  // NewChanQueue creates a ChanQueue by wrapping pq.
    17  func NewChanQueue(ctx context.Context, pq PeerQueue) *ChanQueue {
    18  	cq := &ChanQueue{Queue: pq}
    19  	cq.process(ctx)
    20  	return cq
    21  }
    22  
    23  func (cq *ChanQueue) process(ctx context.Context) {
    24  
    25  	// construct the channels here to be able to use them bidirectionally
    26  	enqChan := make(chan peer.Peer, 10)
    27  	deqChan := make(chan peer.Peer, 10)
    28  
    29  	cq.EnqChan = enqChan
    30  	cq.DeqChan = deqChan
    31  
    32  	go func() {
    33  		defer close(deqChan)
    34  
    35  		var next peer.Peer
    36  		var item peer.Peer
    37  		var more bool
    38  
    39  		for {
    40  			if cq.Queue.Len() == 0 {
    41  				select {
    42  				case next, more = <-enqChan:
    43  					if !more {
    44  						return
    45  					}
    46  
    47  				case <-ctx.Done():
    48  					return
    49  				}
    50  
    51  			} else {
    52  				next = cq.Queue.Dequeue()
    53  			}
    54  
    55  			select {
    56  			case item, more = <-enqChan:
    57  				if !more {
    58  					return
    59  				}
    60  
    61  				cq.Queue.Enqueue(item)
    62  				cq.Queue.Enqueue(next)
    63  				next = nil
    64  
    65  			case deqChan <- next:
    66  				next = nil
    67  
    68  			case <-ctx.Done():
    69  				return
    70  			}
    71  		}
    72  
    73  	}()
    74  }