github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/internal/testutils/channel.go (about)

     1  /*
     2   *
     3   * Copyright 2020 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package testutils
    19  
    20  import (
    21  	"context"
    22  )
    23  
    24  // DefaultChanBufferSize is the default buffer size of the underlying channel.
    25  const DefaultChanBufferSize = 1
    26  
    27  // Channel wraps a generic channel and provides a timed receive operation.
    28  type Channel struct {
    29  	ch chan interface{}
    30  }
    31  
    32  // Send sends value on the underlying channel.
    33  func (c *Channel) Send(value interface{}) {
    34  	c.ch <- value
    35  }
    36  
    37  // SendContext sends value on the underlying channel, or returns an error if
    38  // the context expires.
    39  func (c *Channel) SendContext(ctx context.Context, value interface{}) error {
    40  	select {
    41  	case c.ch <- value:
    42  		return nil
    43  	case <-ctx.Done():
    44  		return ctx.Err()
    45  	}
    46  }
    47  
    48  // SendOrFail attempts to send value on the underlying channel.  Returns true
    49  // if successful or false if the channel was full.
    50  func (c *Channel) SendOrFail(value interface{}) bool {
    51  	select {
    52  	case c.ch <- value:
    53  		return true
    54  	default:
    55  		return false
    56  	}
    57  }
    58  
    59  // ReceiveOrFail returns the value on the underlying channel and true, or nil
    60  // and false if the channel was empty.
    61  func (c *Channel) ReceiveOrFail() (interface{}, bool) {
    62  	select {
    63  	case got := <-c.ch:
    64  		return got, true
    65  	default:
    66  		return nil, false
    67  	}
    68  }
    69  
    70  // Receive returns the value received on the underlying channel, or the error
    71  // returned by ctx if it is closed or cancelled.
    72  func (c *Channel) Receive(ctx context.Context) (interface{}, error) {
    73  	select {
    74  	case <-ctx.Done():
    75  		return nil, ctx.Err()
    76  	case got := <-c.ch:
    77  		return got, nil
    78  	}
    79  }
    80  
    81  // Replace clears the value on the underlying channel, and sends the new value.
    82  //
    83  // It's expected to be used with a size-1 channel, to only keep the most
    84  // up-to-date item. This method is inherently racy when invoked concurrently
    85  // from multiple goroutines.
    86  func (c *Channel) Replace(value interface{}) {
    87  	for {
    88  		select {
    89  		case c.ch <- value:
    90  			return
    91  		case <-c.ch:
    92  		}
    93  	}
    94  }
    95  
    96  // NewChannel returns a new Channel.
    97  func NewChannel() *Channel {
    98  	return NewChannelWithSize(DefaultChanBufferSize)
    99  }
   100  
   101  // NewChannelWithSize returns a new Channel with a buffer of bufSize.
   102  func NewChannelWithSize(bufSize int) *Channel {
   103  	return &Channel{ch: make(chan interface{}, bufSize)}
   104  }