@Override public final synchronized void start(Listener listener) { Preconditions.checkState(this.listener == null, "already started"); timerService = SharedResourceHolder.get(timerServiceResource); executor = SharedResourceHolder.get(executorResource); this.listener = Preconditions.checkNotNull(listener, "listener"); resolve(); }
@Override public final synchronized void shutdown() { if (shutdown) { return; } shutdown = true; if (resolutionTask != null) { resolutionTask.cancel(false); } if (timerService != null) { timerService = SharedResourceHolder.release(timerServiceResource, timerService); } if (executor != null) { executor = SharedResourceHolder.release(executorResource, executor); } }
/** If we're using the shared executor, returns its reference. */ private void onChannelTerminated() { if (usingSharedExecutor) { SharedResourceHolder.release(GrpcUtil.SHARED_CHANNEL_EXECUTOR, (ExecutorService) executor); } // Release the transport factory so that it can deallocate any resources. transportFactory.release(); }
/** * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately * cancelled. */ @Override public ManagedChannelImpl shutdown() { ArrayList<TransportSet> transportsCopy = new ArrayList<TransportSet>(); synchronized (lock) { if (shutdown) { return this; } shutdown = true; // After shutdown there are no new calls, so no new cancellation tasks are needed scheduledExecutor = SharedResourceHolder.release(TIMER_SERVICE, scheduledExecutor); if (transports.isEmpty()) { terminated = true; lock.notifyAll(); onChannelTerminated(); } else { transportsCopy.addAll(transports.values()); } } loadBalancer.shutdown(); nameResolver.shutdown(); for (TransportSet ts : transportsCopy) { ts.shutdown(); } return this; }
ManagedChannelImpl( String target, BackoffPolicy.Provider backoffPolicyProvider, NameResolver.Factory nameResolverFactory, Attributes nameResolverParams, LoadBalancer.Factory loadBalancerFactory, ClientTransportFactory transportFactory, DecompressorRegistry decompressorRegistry, CompressorRegistry compressorRegistry, @Nullable Executor executor, @Nullable String userAgent, List<ClientInterceptor> interceptors) { if (executor == null) { usingSharedExecutor = true; this.executor = SharedResourceHolder.get(GrpcUtil.SHARED_CHANNEL_EXECUTOR); } else { usingSharedExecutor = false; this.executor = executor; } this.backoffPolicyProvider = backoffPolicyProvider; this.nameResolver = getNameResolver(target, nameResolverFactory, nameResolverParams); this.loadBalancer = loadBalancerFactory.newLoadBalancer(nameResolver.getServiceAuthority(), tm); this.transportFactory = transportFactory; this.userAgent = userAgent; this.interceptorChannel = ClientInterceptors.intercept(new RealChannel(), interceptors); scheduledExecutor = SharedResourceHolder.get(TIMER_SERVICE); this.decompressorRegistry = decompressorRegistry; this.compressorRegistry = compressorRegistry; this.nameResolver.start( new NameResolver.Listener() { @Override public void onUpdate(List<ResolvedServerInfo> servers, Attributes config) { loadBalancer.handleResolvedAddresses(servers, config); } @Override public void onError(Status error) { Preconditions.checkArgument(!error.isOk(), "the error status must not be OK"); loadBalancer.handleNameResolutionError(error); } }); }
/** * Try to get an existing instance of the given resource. If an instance does not exist, create a * new one with the given factory. * * @param resource the singleton object that identifies the requested static resource */ public static <T> T get(Resource<T> resource) { return holder.getInternal(resource); }
/** * Releases an instance of the given resource. * * <p>The instance must have been obtained from {@link #get(Resource)}. Otherwise will throw * IllegalArgumentException. * * <p>Caller must not release a reference more than once. It's advisory that you clear the * reference to the instance with the null returned by this method. * * @param resource the singleton Resource object that identifies the released static resource * @param instance the released static resource * @return a null which the caller can use to clear the reference to that instance. */ public static <T> T release(final Resource<T> resource, final T instance) { return holder.releaseInternal(resource, instance); }