github.com/matrixorigin/matrixone@v1.2.0/pkg/fileservice/fifocache/queue.go (about) 1 // Copyright 2024 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fifocache 16 17 import "sync" 18 19 type Queue[T any] struct { 20 head *queuePart[T] 21 tail *queuePart[T] 22 partPool sync.Pool 23 } 24 25 type queuePart[T any] struct { 26 values []T 27 begin int 28 next *queuePart[T] 29 } 30 31 const maxQueuePartCapacity = 256 32 33 func NewQueue[T any]() *Queue[T] { 34 queue := &Queue[T]{ 35 partPool: sync.Pool{ 36 New: func() any { 37 return &queuePart[T]{ 38 values: make([]T, 0, maxQueuePartCapacity), 39 } 40 }, 41 }, 42 } 43 part := queue.partPool.Get().(*queuePart[T]) 44 queue.head = part 45 queue.tail = part 46 return queue 47 } 48 49 func (p *Queue[T]) empty() bool { 50 return p.head == p.tail && 51 p.head.begin == len(p.head.values) 52 } 53 54 func (p *queuePart[T]) reset() { 55 p.values = p.values[:0] 56 p.begin = 0 57 p.next = nil 58 } 59 60 func (p *Queue[T]) enqueue(v T) { 61 if len(p.head.values) >= maxQueuePartCapacity { 62 // extend 63 newPart := p.partPool.Get().(*queuePart[T]) 64 newPart.reset() 65 p.head.next = newPart 66 p.head = newPart 67 } 68 p.head.values = append(p.head.values, v) 69 } 70 71 func (p *Queue[T]) dequeue() (ret T, ok bool) { 72 if p.empty() { 73 return 74 } 75 76 if p.tail.begin >= len(p.tail.values) { 77 // shrink 78 if p.tail.next == nil { 79 panic("impossible") 80 } 81 part := p.tail 82 p.tail = p.tail.next 83 p.partPool.Put(part) 84 } 85 86 ret = p.tail.values[p.tail.begin] 87 p.tail.begin++ 88 ok = true 89 return 90 }