context: Uniformly pass cancelCtx by pointer.

cancelCtx has an embedded sync.Mutex. This change causes an extra
allocation when creating a new timerCtx via WithDeadline, but that seems
minor when compared with better locking discipline. If it turns out to
be a problem, the whole cancelCtx struct can be flattened into timerCtx.

Addresses part of golang/go#14839.

Change-Id: Ie86ed1b63592b521aefde747d5fafcd49ac18178
Reviewed-on: https://go-review.googlesource.com/20840
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
David Symonds
2016-03-18 08:54:57 +11:00
parent 35b06af072
commit 9d8ef8d73b

View File

@@ -210,13 +210,13 @@ type CancelFunc func()
// call cancel as soon as the operations running in this Context complete. // call cancel as soon as the operations running in this Context complete.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent) c := newCancelCtx(parent)
propagateCancel(parent, &c) propagateCancel(parent, c)
return &c, func() { c.cancel(true, Canceled) } return c, func() { c.cancel(true, Canceled) }
} }
// newCancelCtx returns an initialized cancelCtx. // newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx { func newCancelCtx(parent Context) *cancelCtx {
return cancelCtx{ return &cancelCtx{
Context: parent, Context: parent,
done: make(chan struct{}), done: make(chan struct{}),
} }
@@ -259,7 +259,7 @@ func parentCancelCtx(parent Context) (*cancelCtx, bool) {
case *cancelCtx: case *cancelCtx:
return c, true return c, true
case *timerCtx: case *timerCtx:
return &c.cancelCtx, true return c.cancelCtx, true
case *valueCtx: case *valueCtx:
parent = c.Context parent = c.Context
default: default:
@@ -377,7 +377,7 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
// implement Done and Err. It implements cancel by stopping its timer then // implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel. // delegating to cancelCtx.cancel.
type timerCtx struct { type timerCtx struct {
cancelCtx *cancelCtx
timer *time.Timer // Under cancelCtx.mu. timer *time.Timer // Under cancelCtx.mu.
deadline time.Time deadline time.Time