Skip to content

Commit

Permalink
coalescing_context: avoid goroutine when possible
Browse files Browse the repository at this point in the history
We don't need a goroutine until either something has either accessed
the done channel, or is adding a second context.  This avoids having a
goroutine for every outstanding block request, even when the ones that
aren't actively being fetched.

Issue: HOTPOT-2268
  • Loading branch information
strib committed Apr 8, 2020
1 parent ce8677d commit c851155
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion go/kbfs/libkbfs/coalescing_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package libkbfs

import (
"reflect"
"sync"
"time"

"golang.org/x/net/context"
Expand All @@ -17,6 +18,7 @@ type CoalescingContext struct {
doneCh chan struct{}
mutateCh chan context.Context
selects []reflect.SelectCase
start sync.Once
}

const (
Expand Down Expand Up @@ -81,7 +83,6 @@ func NewCoalescingContext(parent context.Context) (*CoalescingContext, context.C
},
}
ctx.appendContext(parent)
go ctx.loop()
cancelFunc := func() {
select {
case <-closeCh:
Expand All @@ -92,6 +93,12 @@ func NewCoalescingContext(parent context.Context) (*CoalescingContext, context.C
return ctx, cancelFunc
}

func (ctx *CoalescingContext) startLoop() {
ctx.start.Do(func() {
go ctx.loop()
})
}

// Deadline overrides the default parent's Deadline().
func (ctx *CoalescingContext) Deadline() (time.Time, bool) {
return time.Time{}, false
Expand All @@ -100,12 +107,14 @@ func (ctx *CoalescingContext) Deadline() (time.Time, bool) {
// Done returns a channel that is closed when the CoalescingContext is
// canceled.
func (ctx *CoalescingContext) Done() <-chan struct{} {
ctx.startLoop()
return ctx.doneCh
}

// Err returns context.Canceled if the CoalescingContext has been canceled, and
// nil otherwise.
func (ctx *CoalescingContext) Err() error {
ctx.startLoop()
select {
case <-ctx.doneCh:
return context.Canceled
Expand All @@ -116,6 +125,7 @@ func (ctx *CoalescingContext) Err() error {

// AddContext adds a context to the set of contexts that we're waiting on.
func (ctx *CoalescingContext) AddContext(other context.Context) error {
ctx.startLoop()
select {
case ctx.mutateCh <- other:
return nil
Expand Down

0 comments on commit c851155

Please sign in to comment.