github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/peer/queue/sync.go (about)

     1  package queue
     2  
     3  import (
     4  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
     5  	peer "github.com/ipfs/go-ipfs/p2p/peer"
     6  	eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
     7  )
     8  
     9  var log = eventlog.Logger("peerqueue")
    10  
    11  // ChanQueue makes any PeerQueue synchronizable through channels.
    12  type ChanQueue struct {
    13  	Queue   PeerQueue
    14  	EnqChan chan<- peer.ID
    15  	DeqChan <-chan peer.ID
    16  }
    17  
    18  // NewChanQueue creates a ChanQueue by wrapping pq.
    19  func NewChanQueue(ctx context.Context, pq PeerQueue) *ChanQueue {
    20  	cq := &ChanQueue{Queue: pq}
    21  	cq.process(ctx)
    22  	return cq
    23  }
    24  
    25  func (cq *ChanQueue) process(ctx context.Context) {
    26  	// construct the channels here to be able to use them bidirectionally
    27  	enqChan := make(chan peer.ID)
    28  	deqChan := make(chan peer.ID)
    29  
    30  	cq.EnqChan = enqChan
    31  	cq.DeqChan = deqChan
    32  
    33  	go func() {
    34  		log.Debug("processing")
    35  		defer log.Debug("closed")
    36  		defer close(deqChan)
    37  
    38  		var next peer.ID
    39  		var item peer.ID
    40  		var more bool
    41  
    42  		for {
    43  			if cq.Queue.Len() == 0 {
    44  				// log.Debug("wait for enqueue")
    45  				select {
    46  				case next, more = <-enqChan:
    47  					if !more {
    48  						return
    49  					}
    50  					// log.Debug("got", next)
    51  
    52  				case <-ctx.Done():
    53  					return
    54  				}
    55  
    56  			} else {
    57  				next = cq.Queue.Dequeue()
    58  				// log.Debug("peek", next)
    59  			}
    60  
    61  			select {
    62  			case item, more = <-enqChan:
    63  				if !more {
    64  					if cq.Queue.Len() > 0 {
    65  						return // we're done done.
    66  					}
    67  					enqChan = nil // closed, so no use.
    68  				}
    69  				// log.Debug("got", item)
    70  				cq.Queue.Enqueue(item)
    71  				cq.Queue.Enqueue(next) // order may have changed.
    72  				next = ""
    73  
    74  			case deqChan <- next:
    75  				// log.Debug("dequeued", next)
    76  				next = ""
    77  
    78  			case <-ctx.Done():
    79  				return
    80  			}
    81  		}
    82  
    83  	}()
    84  }