...

Source file src/golang.org/x/net/http2/gate_test.go

Documentation: golang.org/x/net/http2

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

View as plain text