github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/util/cancel/context.go (about)

     1  // Copyright 2016-2018, Pulumi Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cancel
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
    21  )
    22  
    23  // Context provides the ability to observe cancellation and termination requests from a Source. A termination request
    24  // automatically triggers a corresponding cancellation request. This can be used to implement cancellation with two
    25  // priority levels.
    26  type Context struct {
    27  	terminate context.Context
    28  	cancel    context.Context
    29  }
    30  
    31  // Source provides the ability to deliver cancellation and termination requests to a Context. A termination request
    32  // automatically triggers a corresponding cancellation request. This can be used to implement cancellation with two
    33  // priority levels.
    34  type Source struct {
    35  	context *Context
    36  
    37  	terminate context.CancelFunc
    38  	cancel    context.CancelFunc
    39  }
    40  
    41  // NewContext creates a new cancellation context and source parented to the given context. The returned cancellation
    42  // context will be terminated when the supplied root context is canceled.
    43  func NewContext(ctx context.Context) (*Context, *Source) {
    44  	contract.Require(ctx != nil, "ctx")
    45  
    46  	// Set up two new cancellable contexts: one for termination and one for cancellation. The cancellation context is a
    47  	// child context of the termination context and will therefore be automatically cancelled when termination is
    48  	// requested. Both are children of the supplied context--cancelling the supplied context will cause termination.
    49  	terminationContext, terminate := context.WithCancel(ctx)
    50  	cancellationContext, cancel := context.WithCancel(terminationContext)
    51  
    52  	c := &Context{
    53  		terminate: terminationContext,
    54  		cancel:    cancellationContext,
    55  	}
    56  	s := &Source{
    57  		context:   c,
    58  		terminate: terminate,
    59  		cancel:    cancel,
    60  	}
    61  	return c, s
    62  }
    63  
    64  // Canceled returns a channel that will be closed when the context is canceled or terminated.
    65  func (c *Context) Canceled() <-chan struct{} {
    66  	return c.cancel.Done()
    67  }
    68  
    69  // CancelErr returns a non-nil error iff the context has been canceled or terminated.
    70  func (c *Context) CancelErr() error {
    71  	return c.cancel.Err()
    72  }
    73  
    74  // Terminated returns a channel that will be closed when the context is terminated.
    75  func (c *Context) Terminated() <-chan struct{} {
    76  	return c.terminate.Done()
    77  }
    78  
    79  // TerminateErr returns a non-nil error iff the context has been terminated.
    80  func (c *Context) TerminateErr() error {
    81  	return c.terminate.Err()
    82  }
    83  
    84  // Context returns the Context to which this source will deliver cancellation and termination requests.
    85  func (s *Source) Context() *Context {
    86  	return s.context
    87  }
    88  
    89  // Cancel cancels this source's context.
    90  func (s *Source) Cancel() {
    91  	s.cancel()
    92  }
    93  
    94  // Terminate terminates this source's context (which also cancels this context).
    95  func (s *Source) Terminate() {
    96  	s.terminate()
    97  }