mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 18:36:30 +02:00
88 lines
1.7 KiB
Go
88 lines
1.7 KiB
Go
// Package contextutil contains functions for working with contexts.
|
|
package contextutil
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
type mergedCtx struct {
|
|
ctx1, ctx2 context.Context
|
|
|
|
doneCtx context.Context
|
|
doneCancel context.CancelFunc
|
|
}
|
|
|
|
// Merge merges two contexts into a single context.
|
|
func Merge(ctx1, ctx2 context.Context) (context.Context, context.CancelFunc) {
|
|
mc := &mergedCtx{
|
|
ctx1: ctx1,
|
|
ctx2: ctx2,
|
|
}
|
|
mc.doneCtx, mc.doneCancel = context.WithCancel(context.Background())
|
|
go func() {
|
|
select {
|
|
case <-ctx1.Done():
|
|
case <-ctx2.Done():
|
|
case <-mc.doneCtx.Done():
|
|
}
|
|
mc.doneCancel()
|
|
}()
|
|
return mc, mc.doneCancel
|
|
}
|
|
|
|
func (mc *mergedCtx) Deadline() (deadline time.Time, ok bool) {
|
|
if deadline, ok = mc.ctx1.Deadline(); ok {
|
|
return deadline, ok
|
|
}
|
|
if deadline, ok = mc.ctx2.Deadline(); ok {
|
|
return deadline, ok
|
|
}
|
|
return mc.doneCtx.Deadline()
|
|
}
|
|
|
|
func (mc *mergedCtx) Done() <-chan struct{} {
|
|
return mc.doneCtx.Done()
|
|
}
|
|
|
|
func (mc *mergedCtx) Err() error {
|
|
if err := mc.ctx1.Err(); err != nil {
|
|
return mc.ctx1.Err()
|
|
}
|
|
if err := mc.ctx2.Err(); err != nil {
|
|
return mc.ctx2.Err()
|
|
}
|
|
return mc.doneCtx.Err()
|
|
}
|
|
|
|
func (mc *mergedCtx) Value(key interface{}) interface{} {
|
|
if value := mc.ctx1.Value(key); value != nil {
|
|
return value
|
|
}
|
|
if value := mc.ctx2.Value(key); value != nil {
|
|
return value
|
|
}
|
|
return mc.doneCtx.Value(key)
|
|
}
|
|
|
|
type onlyValues struct {
|
|
context.Context
|
|
}
|
|
|
|
// OnlyValues returns a derived context that removes deadlines and cancellation,
|
|
// but keeps values.
|
|
func OnlyValues(ctx context.Context) context.Context {
|
|
return onlyValues{ctx}
|
|
}
|
|
|
|
func (o onlyValues) Deadline() (time.Time, bool) {
|
|
return time.Time{}, false
|
|
}
|
|
|
|
func (o onlyValues) Done() <-chan struct{} {
|
|
return nil
|
|
}
|
|
|
|
func (o onlyValues) Err() error {
|
|
return nil
|
|
}
|