golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/queue.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 7 package quic 8 9 import "context" 10 11 // A queue is an unbounded queue of some item (new connections and streams). 12 type queue[T any] struct { 13 // The gate condition is set if the queue is non-empty or closed. 14 gate gate 15 err error 16 q []T 17 } 18 19 func newQueue[T any]() queue[T] { 20 return queue[T]{gate: newGate()} 21 } 22 23 // close closes the queue, causing pending and future pop operations 24 // to return immediately with err. 25 func (q *queue[T]) close(err error) { 26 q.gate.lock() 27 defer q.unlock() 28 if q.err == nil { 29 q.err = err 30 } 31 } 32 33 // put appends an item to the queue. 34 // It returns true if the item was added, false if the queue is closed. 35 func (q *queue[T]) put(v T) bool { 36 q.gate.lock() 37 defer q.unlock() 38 if q.err != nil { 39 return false 40 } 41 q.q = append(q.q, v) 42 return true 43 } 44 45 // get removes the first item from the queue, blocking until ctx is done, an item is available, 46 // or the queue is closed. 47 func (q *queue[T]) get(ctx context.Context, testHooks connTestHooks) (T, error) { 48 var zero T 49 if err := q.gate.waitAndLock(ctx, testHooks); err != nil { 50 return zero, err 51 } 52 defer q.unlock() 53 if q.err != nil { 54 return zero, q.err 55 } 56 v := q.q[0] 57 copy(q.q[:], q.q[1:]) 58 q.q[len(q.q)-1] = zero 59 q.q = q.q[:len(q.q)-1] 60 return v, nil 61 } 62 63 func (q *queue[T]) unlock() { 64 q.gate.unlock(q.err != nil || len(q.q) > 0) 65 }