github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/xcontext/context_with_cancel.go (about)

     1  package xcontext
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"time"
     7  )
     8  
     9  func WithCancel(ctx context.Context) (context.Context, context.CancelFunc) {
    10  	childCtx := &cancelCtx{
    11  		parentCtx: ctx,
    12  	}
    13  	childCtx.ctx, childCtx.ctxCancel = context.WithCancel(ctx)
    14  
    15  	return childCtx, childCtx.cancel
    16  }
    17  
    18  type cancelCtx struct {
    19  	parentCtx context.Context
    20  	ctx       context.Context
    21  	ctxCancel context.CancelFunc
    22  
    23  	m   sync.Mutex
    24  	err error
    25  }
    26  
    27  func (ctx *cancelCtx) Deadline() (deadline time.Time, ok bool) {
    28  	return ctx.ctx.Deadline()
    29  }
    30  
    31  func (ctx *cancelCtx) Done() <-chan struct{} {
    32  	return ctx.ctx.Done()
    33  }
    34  
    35  func (ctx *cancelCtx) Err() error {
    36  	ctx.m.Lock()
    37  	defer ctx.m.Unlock()
    38  
    39  	if ctx.err != nil {
    40  		return ctx.err
    41  	}
    42  
    43  	ctx.err = ctx.ctx.Err()
    44  
    45  	return ctx.err
    46  }
    47  
    48  func (ctx *cancelCtx) Value(key interface{}) interface{} {
    49  	return ctx.ctx.Value(key)
    50  }
    51  
    52  func (ctx *cancelCtx) cancel() {
    53  	ctx.m.Lock()
    54  	defer ctx.m.Unlock()
    55  
    56  	ctx.ctxCancel()
    57  
    58  	if ctx.err != nil {
    59  		return
    60  	}
    61  
    62  	if err := ctx.parentCtx.Err(); err != nil {
    63  		ctx.err = err
    64  
    65  		return
    66  	}
    67  	ctx.err = errAt(context.Canceled, 1)
    68  }