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  

View as plain text