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  }