@@ -144,7 +144,7 @@ type (
144144 // CoDelQueue implements the CoDel (Controlled Delay) load-shedding
145145 // algorithm. All methods are prefixed locked* and assume the caller holds
146146 // the mutex, which is defined in the files for the higher-level structure
147- CoDelQueue struct {
147+ CoDelQueue [ T any ] struct {
148148 queue * list.List
149149 dropping bool
150150 dropNextNs int64
@@ -153,16 +153,16 @@ type (
153153 // droppable indexes the droppable queue entries by priority so the
154154 // lowest-priority one is found in O(1) rather than an O(n) scan. Kept in
155155 // lockstep with droppableLen: every insert/remove pairs with a ++/--.
156- droppable droppableIndex
156+ droppable droppableIndex [ T ]
157157
158158 cfg CoDelConfig
159159 nowNs func () int64
160160 scheduleDropTimer func (delayNs int64 )
161161 }
162162)
163163
164- func newCoDelQueue (cfg CoDelConfig , nowNs func () int64 , scheduleDropTimer func (delayNs int64 )) * CoDelQueue {
165- q := & CoDelQueue {
164+ func newCoDelQueue [ T any ] (cfg CoDelConfig , nowNs func () int64 , scheduleDropTimer func (delayNs int64 )) * CoDelQueue [ T ] {
165+ q := & CoDelQueue [ T ] {
166166 queue : list .New (),
167167 count : 1 ,
168168 cfg : cfg ,
@@ -173,15 +173,15 @@ func newCoDelQueue(cfg CoDelConfig, nowNs func() int64, scheduleDropTimer func(d
173173 return q
174174}
175175
176- func (q * CoDelQueue ) lockedLen () int {
176+ func (q * CoDelQueue [ T ] ) lockedLen () int {
177177 return q .queue .Len ()
178178}
179179
180- func (q * CoDelQueue ) lockedIsHealthy () bool {
180+ func (q * CoDelQueue [ T ] ) lockedIsHealthy () bool {
181181 return ! q .dropping
182182}
183183
184- func (q * CoDelQueue ) lockedEnqueue (req * Request ) {
184+ func (q * CoDelQueue [ T ] ) lockedEnqueue (req * Request [ T ] ) {
185185 now := q .nowNs ()
186186
187187 req .codelqEnqueuedAtNs = now
@@ -204,16 +204,16 @@ func (q *CoDelQueue) lockedEnqueue(req *Request) {
204204}
205205
206206// lockedFirstWaiting returns the first waiting request in the queue.
207- func (q * CoDelQueue ) lockedFirstWaiting () * Request {
207+ func (q * CoDelQueue [ T ] ) lockedFirstWaiting () * Request [ T ] {
208208 first := q .queue .Front ()
209209 if first == nil {
210210 return nil
211211 }
212- return first .Value .(* Request )
212+ return first .Value .(* Request [ T ] )
213213}
214214
215215// lockedRemove removes a specific request from the queue.
216- func (q * CoDelQueue ) lockedRemove (r * Request ) {
216+ func (q * CoDelQueue [ T ] ) lockedRemove (r * Request [ T ] ) {
217217 if r .codelqElem == nil {
218218 return
219219 }
@@ -230,7 +230,7 @@ func (q *CoDelQueue) lockedRemove(r *Request) {
230230 }
231231}
232232
233- func (q * CoDelQueue ) lockedDequeue (r * Request ) {
233+ func (q * CoDelQueue [ T ] ) lockedDequeue (r * Request [ T ] ) {
234234 // CoDel health check, measured at dequeue: if this request's queue-wait
235235 // (now - enqueue) was under target, the system is healthy — leave the
236236 // dropping state. Separate from the droppableLen==0 clear below.
@@ -243,7 +243,7 @@ func (q *CoDelQueue) lockedDequeue(r *Request) {
243243// lockedFindLowestPriorityDroppable finds the lowest-priority droppable
244244// element in the queue — the oldest one at the lowest priority present — or nil
245245// if none exists. O(1) via the droppable priority index (see droppableIndex).
246- func (q * CoDelQueue ) lockedFindLowestPriorityDroppable () * list.Element {
246+ func (q * CoDelQueue [ T ] ) lockedFindLowestPriorityDroppable () * list.Element {
247247 req := q .droppable .min ()
248248 if req == nil {
249249 return nil
@@ -254,11 +254,11 @@ func (q *CoDelQueue) lockedFindLowestPriorityDroppable() *list.Element {
254254// lockedRunTimer runs the CoDel drop logic. It is invoked both by the backstop
255255// timer and synchronously from the dequeue path, so shedding is driven
256256// as slots free rather than waiting for the (possibly late) timer to fire.
257- func (q * CoDelQueue ) lockedRunTimer (dropFn func () bool ) {
257+ func (q * CoDelQueue [ T ] ) lockedRunTimer (dropFn func () bool ) {
258258 q .lockedRunTimerLimited (dropFn , - 1 )
259259}
260260
261- func (q * CoDelQueue ) lockedRunTimerLimited (dropFn func () bool , maxDrops int ) {
261+ func (q * CoDelQueue [ T ] ) lockedRunTimerLimited (dropFn func () bool , maxDrops int ) {
262262 now := q .nowNs ()
263263
264264 // Paced work: only advance the drop/ease control law and re-arm when a drop
@@ -282,11 +282,11 @@ func (q *CoDelQueue) lockedRunTimerLimited(dropFn func() bool, maxDrops int) {
282282// `now`, so calling it is idempotent and safe outside the timer — the dequeue
283283// path invokes it to shed stale requests in real time rather than
284284// waiting on the possibly-late backstop timer. It does NOT arm/disarm the timer.
285- func (q * CoDelQueue ) lockedAdvance (now int64 , dropFn func () bool ) {
285+ func (q * CoDelQueue [ T ] ) lockedAdvance (now int64 , dropFn func () bool ) {
286286 q .lockedAdvanceLimited (now , dropFn , - 1 )
287287}
288288
289- func (q * CoDelQueue ) lockedAdvanceLimited (now int64 , dropFn func () bool , maxDrops int ) {
289+ func (q * CoDelQueue [ T ] ) lockedAdvanceLimited (now int64 , dropFn func () bool , maxDrops int ) {
290290 drops := 0
291291 // Step the control law per interval while a drop is due AND there is still
292292 // work to do: either a droppable backlog to shed, or an elevated count that
@@ -325,7 +325,7 @@ func (q *CoDelQueue) lockedAdvanceLimited(now int64, dropFn func() bool, maxDrop
325325// lockedEaseCount returns the next drop count during easing:
326326// count -= floor(log_base(count) / base), floored at 1. A larger base yields a
327327// smaller step (gentler ease-out); base defaults to 3 when unset or <= 1.
328- func (q * CoDelQueue ) lockedEaseCount () int {
328+ func (q * CoDelQueue [ T ] ) lockedEaseCount () int {
329329 base := 3.0
330330 if q .cfg .EasingLogBase != nil {
331331 base = q .cfg .EasingLogBase ()
@@ -341,15 +341,15 @@ func (q *CoDelQueue) lockedEaseCount() int {
341341// inverse proportion to count^exponent, exploiting the non-linear
342342// relationship between drop rate and throughput to achieve linear change
343343// in throughput.
344- func (q * CoDelQueue ) lockedControlLaw (t int64 ) int64 {
344+ func (q * CoDelQueue [ T ] ) lockedControlLaw (t int64 ) int64 {
345345 return t + q .lockedCurrentInterval ()
346346}
347347
348348// lockedCurrentInterval returns the current interval for the control law.
349349// The interval is compressed whenever count > 1 — both in the dropping state
350350// and during easing (!dropping, count > 1), so that the ease-out timer fires
351351// at progressively longer intervals as the count decays toward 1.
352- func (q * CoDelQueue ) lockedCurrentInterval () int64 {
352+ func (q * CoDelQueue [ T ] ) lockedCurrentInterval () int64 {
353353 interval := q .cfg .IntervalNs ()
354354 if q .count <= 1 {
355355 return interval
@@ -360,7 +360,7 @@ func (q *CoDelQueue) lockedCurrentInterval() int64 {
360360 return max (result , 1 )
361361}
362362
363- func (q * CoDelQueue ) lockedArmDropTimer () {
363+ func (q * CoDelQueue [ T ] ) lockedArmDropTimer () {
364364 // Mark the episode active for this armed interval; the next timer fire
365365 // re-evaluates health.
366366 q .dropping = q .droppableLen > 0
0 commit comments