/* GENERATED SOURCE. DO NOT MODIFY. */ /* * Copyright (C) 2013 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.okhttp; import com.android.okhttp.Call.AsyncCall; import com.android.okhttp.internal.Util; import com.android.okhttp.internal.http.HttpEngine; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.concurrent.ExecutorService; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * Policy on when async requests are executed. * *
Each dispatcher uses an {@link ExecutorService} to run calls internally. If you
* supply your own executor, it should be able to run {@linkplain #getMaxRequests the
* configured maximum} number of calls concurrently.
* @hide This class is not part of the Android public SDK API
*/
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
/** Executes calls. Created lazily. */
private ExecutorService executorService;
/** Ready calls in the order they'll be run. */
private final Deque If more than {@code maxRequests} requests are in flight when this is
* invoked, those requests will remain in flight.
*/
public synchronized void setMaxRequests(int maxRequests) {
if (maxRequests < 1) {
throw new IllegalArgumentException("max < 1: " + maxRequests);
}
this.maxRequests = maxRequests;
promoteCalls();
}
public synchronized int getMaxRequests() {
return maxRequests;
}
/**
* Set the maximum number of requests for each host to execute concurrently.
* This limits requests by the URL's host name. Note that concurrent requests
* to a single IP address may still exceed this limit: multiple hostnames may
* share an IP address or be routed through the same HTTP proxy.
*
* If more than {@code maxRequestsPerHost} requests are in flight when this
* is invoked, those requests will remain in flight.
*/
public synchronized void setMaxRequestsPerHost(int maxRequestsPerHost) {
if (maxRequestsPerHost < 1) {
throw new IllegalArgumentException("max < 1: " + maxRequestsPerHost);
}
this.maxRequestsPerHost = maxRequestsPerHost;
promoteCalls();
}
public synchronized int getMaxRequestsPerHost() {
return maxRequestsPerHost;
}
synchronized void enqueue(AsyncCall call) {
if (runningCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningCalls.add(call);
getExecutorService().execute(call);
} else {
readyCalls.add(call);
}
}
/** Cancel all calls with the tag {@code tag}. */
public synchronized void cancel(Object tag) {
for (AsyncCall call : readyCalls) {
if (Util.equal(tag, call.tag())) {
call.cancel();
}
}
for (AsyncCall call : runningCalls) {
if (Util.equal(tag, call.tag())) {
call.get().canceled = true;
HttpEngine engine = call.get().engine;
if (engine != null) engine.cancel();
}
}
for (Call call : executedCalls) {
if (Util.equal(tag, call.tag())) {
call.cancel();
}
}
}
/** Used by {@code AsyncCall#run} to signal completion. */
synchronized void finished(AsyncCall call) {
if (!runningCalls.remove(call)) throw new AssertionError("AsyncCall wasn't running!");
promoteCalls();
}
private void promoteCalls() {
if (runningCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator