k8s.io/apiserver@v0.31.1/pkg/util/flowcontrol/fairqueuing/queueset/fifo_list.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package queueset 18 19 import ( 20 "container/list" 21 ) 22 23 // removeFromFIFOFunc removes a designated element from the list 24 // if that element is in the list. 25 // The complexity of the runtime cost is O(1). 26 // The returned value is the element removed, if indeed one was removed, 27 // otherwise `nil`. 28 type removeFromFIFOFunc func() *request 29 30 // walkFunc is called for each request in the list in the 31 // oldest -> newest order. 32 // ok: if walkFunc returns false then the iteration stops immediately. 33 // walkFunc may remove the given request from the fifo, 34 // but may not mutate the fifo in any othe way. 35 type walkFunc func(*request) (ok bool) 36 37 // Internal interface to abstract out the implementation details 38 // of the underlying list used to maintain the requests. 39 // 40 // Note that a fifo, including the removeFromFIFOFuncs returned from Enqueue, 41 // is not safe for concurrent use by multiple goroutines. 42 type fifo interface { 43 // Enqueue enqueues the specified request into the list and 44 // returns a removeFromFIFOFunc function that can be used to remove the 45 // request from the list 46 Enqueue(*request) removeFromFIFOFunc 47 48 // Dequeue pulls out the oldest request from the list. 49 Dequeue() (*request, bool) 50 51 // Peek returns the oldest request without removing it. 52 Peek() (*request, bool) 53 54 // Length returns the number of requests in the list. 55 Length() int 56 57 // QueueSum returns the sum of initial seats, final seats, and 58 // additional latency aggregated from all requests in this queue. 59 QueueSum() queueSum 60 61 // Walk iterates through the list in order of oldest -> newest 62 // and executes the specified walkFunc for each request in that order. 63 // 64 // if the specified walkFunc returns false the Walk function 65 // stops the walk an returns immediately. 66 Walk(walkFunc) 67 } 68 69 // the FIFO list implementation is not safe for concurrent use by multiple 70 // goroutines. 71 type requestFIFO struct { 72 *list.List 73 74 sum queueSum 75 } 76 77 func newRequestFIFO() fifo { 78 return &requestFIFO{ 79 List: list.New(), 80 } 81 } 82 83 func (l *requestFIFO) Length() int { 84 return l.Len() 85 } 86 87 func (l *requestFIFO) QueueSum() queueSum { 88 return l.sum 89 } 90 91 func (l *requestFIFO) Enqueue(req *request) removeFromFIFOFunc { 92 e := l.PushBack(req) 93 addToQueueSum(&l.sum, req) 94 95 return func() *request { 96 if e.Value == nil { 97 return nil 98 } 99 l.Remove(e) 100 e.Value = nil 101 deductFromQueueSum(&l.sum, req) 102 return req 103 } 104 } 105 106 func (l *requestFIFO) Dequeue() (*request, bool) { 107 return l.getFirst(true) 108 } 109 110 func (l *requestFIFO) Peek() (*request, bool) { 111 return l.getFirst(false) 112 } 113 114 func (l *requestFIFO) getFirst(remove bool) (*request, bool) { 115 e := l.Front() 116 if e == nil { 117 return nil, false 118 } 119 120 if remove { 121 defer func() { 122 l.Remove(e) 123 e.Value = nil 124 }() 125 } 126 127 request, ok := e.Value.(*request) 128 if remove && ok { 129 deductFromQueueSum(&l.sum, request) 130 } 131 return request, ok 132 } 133 134 func (l *requestFIFO) Walk(f walkFunc) { 135 var next *list.Element 136 for current := l.Front(); current != nil; current = next { 137 next = current.Next() // f is allowed to remove current 138 if r, ok := current.Value.(*request); ok { 139 if !f(r) { 140 return 141 } 142 } 143 } 144 } 145 146 func addToQueueSum(sum *queueSum, req *request) { 147 sum.InitialSeatsSum += req.InitialSeats() 148 sum.MaxSeatsSum += req.MaxSeats() 149 sum.TotalWorkSum += req.totalWork() 150 } 151 152 func deductFromQueueSum(sum *queueSum, req *request) { 153 sum.InitialSeatsSum -= req.InitialSeats() 154 sum.MaxSeatsSum -= req.MaxSeats() 155 sum.TotalWorkSum -= req.totalWork() 156 }