github.com/blend/go-sdk@v1.20220411.3/collections/channel_queue.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package collections 9 10 import "sync" 11 12 // NewChannelQueueWithCapacity returns a new ChannelQueue instance. 13 func NewChannelQueueWithCapacity(capacity int) *ChannelQueue { 14 return &ChannelQueue{Capacity: capacity, storage: make(chan interface{}, capacity), latch: sync.Mutex{}} 15 } 16 17 // NewChannelQueueFromValues returns a new ChannelQueue from a given slice of values. 18 func NewChannelQueueFromValues(values []interface{}) *ChannelQueue { 19 capacity := len(values) 20 cq := &ChannelQueue{Capacity: capacity, storage: make(chan interface{}, capacity), latch: sync.Mutex{}} 21 for _, v := range values { 22 cq.storage <- v 23 } 24 return cq 25 } 26 27 // ChannelQueue is a threadsafe queue. 28 type ChannelQueue struct { 29 Capacity int 30 storage chan interface{} 31 latch sync.Mutex 32 } 33 34 // Len returns the number of items in the queue. 35 func (cq *ChannelQueue) Len() int { 36 return len(cq.storage) 37 } 38 39 // Enqueue adds an item to the queue. 40 func (cq *ChannelQueue) Enqueue(item interface{}) { 41 cq.storage <- item 42 } 43 44 // Dequeue returns the next element in the queue. 45 func (cq *ChannelQueue) Dequeue() interface{} { 46 if len(cq.storage) != 0 { 47 return <-cq.storage 48 } 49 return nil 50 } 51 52 // DequeueBack iterates over the queue, removing the last element and returning it 53 func (cq *ChannelQueue) DequeueBack() interface{} { 54 values := []interface{}{} 55 storageLen := len(cq.storage) 56 for x := 0; x < storageLen; x++ { 57 v := <-cq.storage 58 values = append(values, v) 59 } 60 var output interface{} 61 for index, v := range values { 62 if index == len(values)-1 { 63 output = v 64 } else { 65 cq.storage <- v 66 } 67 } 68 return output 69 } 70 71 // Peek returns (but does not remove) the first element of the queue. 72 func (cq *ChannelQueue) Peek() interface{} { 73 if len(cq.storage) == 0 { 74 return nil 75 } 76 return cq.Contents()[0] 77 } 78 79 // PeekBack returns (but does not remove) the last element of the queue. 80 func (cq *ChannelQueue) PeekBack() interface{} { 81 if len(cq.storage) == 0 { 82 return nil 83 } 84 return cq.Contents()[len(cq.storage)-1] 85 } 86 87 // Clear clears the queue. 88 func (cq *ChannelQueue) Clear() { 89 cq.storage = make(chan interface{}, cq.Capacity) 90 } 91 92 // Each pulls every value out of the channel, calls consumer on it, and puts it back. 93 func (cq *ChannelQueue) Each(consumer func(value interface{})) { 94 if len(cq.storage) == 0 { 95 return 96 } 97 values := []interface{}{} 98 for len(cq.storage) != 0 { 99 v := <-cq.storage 100 consumer(v) 101 values = append(values, v) 102 } 103 for _, v := range values { 104 cq.storage <- v 105 } 106 } 107 108 // Consume pulls every value out of the channel, calls consumer on it, effectively clearing the queue. 109 func (cq *ChannelQueue) Consume(consumer func(value interface{})) { 110 if len(cq.storage) == 0 { 111 return 112 } 113 for len(cq.storage) != 0 { 114 v := <-cq.storage 115 consumer(v) 116 } 117 } 118 119 // EachUntil pulls every value out of the channel, calls consumer on it, and puts it back and can abort mid process. 120 func (cq *ChannelQueue) EachUntil(consumer func(value interface{}) bool) { 121 contents := cq.Contents() 122 for x := 0; x < len(contents); x++ { 123 if consumer(contents[x]) { 124 return 125 } 126 } 127 } 128 129 // ReverseEachUntil pulls every value out of the channel, calls consumer on it, and puts it back and can abort mid process. 130 func (cq *ChannelQueue) ReverseEachUntil(consumer func(value interface{}) bool) { 131 contents := cq.Contents() 132 for x := len(contents) - 1; x >= 0; x-- { 133 if consumer(contents[x]) { 134 return 135 } 136 } 137 } 138 139 // Contents iterates over the queue and returns an array of its contents. 140 func (cq *ChannelQueue) Contents() []interface{} { 141 values := []interface{}{} 142 storageLen := len(cq.storage) 143 for x := 0; x < storageLen; x++ { 144 v := <-cq.storage 145 values = append(values, v) 146 } 147 for _, v := range values { 148 cq.storage <- v 149 } 150 return values 151 } 152 153 // Drain iterates over the queue and returns an array of its contents, leaving it empty. 154 func (cq *ChannelQueue) Drain() []interface{} { 155 values := []interface{}{} 156 for len(cq.storage) != 0 { 157 v := <-cq.storage 158 values = append(values, v) 159 } 160 return values 161 }