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 }