Repository: grpc/grpc-go
File: balancer/endpointsharding/endpointsharding.go (Go)

Code before:
		enableAutoReconnect: autoReconnect,
	}
	es.children.Store(resolver.NewEndpointMap())
	return es
}

// endpointSharding is a balancer that wraps child balancers. It creates a child
// balancer with child config for every unique Endpoint received. It updates the
// child states on any update from parent or child.
type endpointSharding struct {
	cc                  balancer.ClientConn
	bOpts               balancer.BuildOptions
	enableAutoReconnect bool

	// childMu synchronizes calls to any single child. It must be held for all
	// calls into a child. To avoid deadlocks, do not acquire childMu while
	// holding mu.
	childMu  sync.Mutex
	children atomic.Pointer[resolver.EndpointMap]

	// inhibitChildUpdates is set during UpdateClientConnState/ResolverError
	// calls (calls to children will each produce an update, only want one
	// update).
	inhibitChildUpdates atomic.Bool

	// mu synchronizes access to the stored children balancer states.
	// It must not be held during calls into a child since synchronous calls
	// back from the child may require taking mu, causing a deadlock. To avoid
	// deadlocks, do not acquire childMu while holding mu.
	mu sync.Mutex
}

// UpdateClientConnState creates a child for new endpoints and deletes children
// for endpoints that are no longer present. It also updates all the children,
// and sends a single synchronous update of the childrens' aggregated state at
// the end of the UpdateClientConnState operation. If any endpoint has no
// addresses it will ignore that endpoint. Otherwise, returns first error found
// from a child, but fully processes the new update.
func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState) error {
	es.childMu.Lock()
	defer es.childMu.Unlock()

	es.inhibitChildUpdates.Store(true)
	defer func() {
		es.inhibitChildUpdates.Store(false)
		es.updateState()
	}()
	var ret error

	children := es.children.Load()
	newChildren := resolver.NewEndpointMap()

Review comment (suggestion):
```suggestion
	// mu synchronizes access to the stored children balancer states in children.
```

?

Or "in the children field" or something to be more specific.

Code after:
		enableAutoReconnect: autoReconnect,
	}
	es.children.Store(resolver.NewEndpointMap())
	return es
}

// endpointSharding is a balancer that wraps child balancers. It creates a child
// balancer with child config for every unique Endpoint received. It updates the
// child states on any update from parent or child.
type endpointSharding struct {
	cc                  balancer.ClientConn
	bOpts               balancer.BuildOptions
	enableAutoReconnect bool

	// childMu synchronizes calls to any single child. It must be held for all
	// calls into a child. To avoid deadlocks, do not acquire childMu while
	// holding mu.
	childMu  sync.Mutex
	children atomic.Pointer[resolver.EndpointMap] // endpoint -> *balancerWrapper

	// inhibitChildUpdates is set during UpdateClientConnState/ResolverError
	// calls (calls to children will each produce an update, only want one
	// update).
	inhibitChildUpdates atomic.Bool

	// mu synchronizes access to the state stored in balancerWrappers in the
	// children field. mu must not be held during calls into a child since
	// synchronous calls back from the child may require taking mu, causing a
	// deadlock. To avoid deadlocks, do not acquire childMu while holding mu.
	mu sync.Mutex
}

// UpdateClientConnState creates a child for new endpoints and deletes children
// for endpoints that are no longer present. It also updates all the children,
// and sends a single synchronous update of the childrens' aggregated state at
// the end of the UpdateClientConnState operation. If any endpoint has no
// addresses it will ignore that endpoint. Otherwise, returns first error found
// from a child, but fully processes the new update.
func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState) error {
	es.childMu.Lock()
	defer es.childMu.Unlock()

	es.inhibitChildUpdates.Store(true)
	defer func() {
		es.inhibitChildUpdates.Store(false)
		es.updateState()
	}()
	var ret error

	children := es.children.Load()
	newChildren := resolver.NewEndpointMap()