|  | @@ -94,12 +94,7 @@ class SubchannelData {
 | 
	
		
			
				|  |  |      return curr_connectivity_state_;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // Sets the connected subchannel from the subchannel.
 | 
	
		
			
				|  |  | -  void SetConnectedSubchannelFromSubchannelLocked() {
 | 
	
		
			
				|  |  | -    connected_subchannel_ =
 | 
	
		
			
				|  |  | -        grpc_subchannel_get_connected_subchannel(subchannel_);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +// FIXME: remove
 | 
	
		
			
				|  |  |    // An alternative to SetConnectedSubchannelFromSubchannelLocked() for
 | 
	
		
			
				|  |  |    // cases where we are retaining a connected subchannel from a previous
 | 
	
		
			
				|  |  |    // subchannel list.  This is slightly more efficient than getting the
 | 
	
	
		
			
				|  | @@ -191,10 +186,16 @@ class SubchannelData {
 | 
	
		
			
				|  |  |    // OnConnectivityChangedLocked().
 | 
	
		
			
				|  |  |    grpc_connectivity_state pending_connectivity_state_unsafe_;
 | 
	
		
			
				|  |  |    // Current connectivity state.
 | 
	
		
			
				|  |  | +// FIXME: move this into RR, not needed in PF because connectivity_state
 | 
	
		
			
				|  |  | +// is only used in ProcessConnectivityChangeLocked()
 | 
	
		
			
				|  |  | +// (maybe pass it as a param and eliminate the accessor method?)
 | 
	
		
			
				|  |  |    grpc_connectivity_state curr_connectivity_state_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // A list of subchannels.
 | 
	
		
			
				|  |  | +// FIXME: make this InternallyRefCounted, and have Orphan() do
 | 
	
		
			
				|  |  | +// ShutdownLocked()?
 | 
	
		
			
				|  |  | +// (also, maybe we don't need to take a ref to the LB policy anymore?)
 | 
	
		
			
				|  |  |  template <typename SubchannelListType, typename SubchannelDataType>
 | 
	
		
			
				|  |  |  class SubchannelList : public RefCountedWithTracing<SubchannelListType> {
 | 
	
		
			
				|  |  |   public:
 | 
	
	
		
			
				|  | @@ -348,14 +349,36 @@ template <typename SubchannelListType, typename SubchannelDataType>
 | 
	
		
			
				|  |  |  void SubchannelData<SubchannelListType, SubchannelDataType>::
 | 
	
		
			
				|  |  |      OnConnectivityChangedLocked(void* arg, grpc_error* error) {
 | 
	
		
			
				|  |  |    SubchannelData* sd = static_cast<SubchannelData*>(arg);
 | 
	
		
			
				|  |  | +// FIXME: add trace logging
 | 
	
		
			
				|  |  | +  // If the subchannel is READY, get a ref to the connected subchannel.
 | 
	
		
			
				|  |  | +  if (sd->pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) {
 | 
	
		
			
				|  |  | +    sd->connected_subchannel_ =
 | 
	
		
			
				|  |  | +        grpc_subchannel_get_connected_subchannel(sd->subchannel_);
 | 
	
		
			
				|  |  | +    // If the subchannel became disconnected between the time that this
 | 
	
		
			
				|  |  | +    // callback was scheduled and the time that it was actually run in the
 | 
	
		
			
				|  |  | +    // combiner, then the connected subchannel may have disappeared out from
 | 
	
		
			
				|  |  | +    // under us.  In that case, instead of propagating the READY notification,
 | 
	
		
			
				|  |  | +    // we simply renew our watch and wait for the next notification.
 | 
	
		
			
				|  |  | +    // Note that we start the renewed watch from IDLE to make sure we
 | 
	
		
			
				|  |  | +    // get a notification for the next state, even if that state is
 | 
	
		
			
				|  |  | +    // READY again (e.g., if the subchannel has transitioned back to
 | 
	
		
			
				|  |  | +    // READY before the callback gets scheduled).
 | 
	
		
			
				|  |  | +    if (sd->connected_subchannel_ == nullptr) {
 | 
	
		
			
				|  |  | +      sd->pending_connectivity_state_unsafe_ = GRPC_CHANNEL_IDLE;
 | 
	
		
			
				|  |  | +      sd->StartConnectivityWatchLocked();
 | 
	
		
			
				|  |  | +      return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  // If we get TRANSIENT_FAILURE, unref the connected subchannel.
 | 
	
		
			
				|  |  | +  else if (sd->pending_connectivity_state_unsafe_ ==
 | 
	
		
			
				|  |  | +           GRPC_CHANNEL_TRANSIENT_FAILURE) {
 | 
	
		
			
				|  |  | +    sd->connected_subchannel_.reset();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    // Now that we're inside the combiner, copy the pending connectivity
 | 
	
		
			
				|  |  |    // state (which was set by the connectivity state watcher) to
 | 
	
		
			
				|  |  |    // curr_connectivity_state_, which is what we use inside of the combiner.
 | 
	
		
			
				|  |  |    sd->curr_connectivity_state_ = sd->pending_connectivity_state_unsafe_;
 | 
	
		
			
				|  |  | -  // If we get TRANSIENT_FAILURE, unref the connected subchannel.
 | 
	
		
			
				|  |  | -  if (sd->curr_connectivity_state_ == GRPC_CHANNEL_TRANSIENT_FAILURE) {
 | 
	
		
			
				|  |  | -    sd->connected_subchannel_.reset();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  // Call the subclass's ProcessConnectivityChangeLocked() method.
 | 
	
		
			
				|  |  |    sd->ProcessConnectivityChangeLocked(GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |