Source file src/vendor/golang.org/x/net/quic/gate.go
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 package quic 6 7 import "context" 8 9 // An gate is a monitor (mutex + condition variable) with one bit of state. 10 // 11 // The condition may be either set or unset. 12 // Lock operations may be unconditional, or wait for the condition to be set. 13 // Unlock operations record the new state of the condition. 14 type gate struct { 15 // When unlocked, exactly one of set or unset contains a value. 16 // When locked, neither chan contains a value. 17 set chan struct{} 18 unset chan struct{} 19 } 20 21 // newGate returns a new, unlocked gate with the condition unset. 22 func newGate() gate { 23 g := newLockedGate() 24 g.unlock(false) 25 return g 26 } 27 28 // newLockedGate returns a new, locked gate. 29 func newLockedGate() gate { 30 return gate{ 31 set: make(chan struct{}, 1), 32 unset: make(chan struct{}, 1), 33 } 34 } 35 36 // lock acquires the gate unconditionally. 37 // It reports whether the condition is set. 38 func (g *gate) lock() (set bool) { 39 select { 40 case <-g.set: 41 return true 42 case <-g.unset: 43 return false 44 } 45 } 46 47 // waitAndLock waits until the condition is set before acquiring the gate. 48 // If the context expires, waitAndLock returns an error and does not acquire the gate. 49 func (g *gate) waitAndLock(ctx context.Context) error { 50 select { 51 case <-g.set: 52 return nil 53 default: 54 } 55 select { 56 case <-g.set: 57 return nil 58 case <-ctx.Done(): 59 return ctx.Err() 60 } 61 } 62 63 // lockIfSet acquires the gate if and only if the condition is set. 64 func (g *gate) lockIfSet() (acquired bool) { 65 select { 66 case <-g.set: 67 return true 68 default: 69 return false 70 } 71 } 72 73 // unlock sets the condition and releases the gate. 74 func (g *gate) unlock(set bool) { 75 if set { 76 g.set <- struct{}{} 77 } else { 78 g.unset <- struct{}{} 79 } 80 } 81 82 // unlockFunc sets the condition to the result of f and releases the gate. 83 // Useful in defers. 84 func (g *gate) unlockFunc(f func() bool) { 85 g.unlock(f()) 86 } 87