func MergeCancellation()

in ctxtool/merge.go [66:103]


func MergeCancellation(parent, other canceller) (context.Context, context.CancelFunc) {
	ctx := FromCanceller(parent)

	err := ctx.Err()
	if err == nil {
		err = other.Err()
	}
	if err != nil {
		// at least one context is already cancelled
		return &cancelledContext{Context: ctx, err: err}, func() {}
	}

	if ctx.Done() == nil {
		if other.Done() == nil {
			// context is never cancelled.
			return ctx, func() {}
		}
		return &cancelOverwriteContext{ctx: ctx, cancel: other}, func() {}
	}

	chDone := make(chan struct{})
	merged := &mergeCancelCtx{
		Context: ctx,
		cancel:  other,
		ch:      chDone,
	}
	go merged.waitCancel(chDone)

	canceller := func() {
		merged.mu.Lock()
		defer merged.mu.Unlock()
		if merged.err == nil {
			merged.err = context.Canceled
			close(chDone)
		}
	}
	return merged, canceller
}