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 }