Index: components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java |
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java |
index f3d376c0278596dad3c9f4f81239fc7e8564f5a0..b98f16ae7b3e7e0f9fb6ef8c7669825f61d5a422 100644 |
--- a/components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java |
+++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java |
@@ -5,10 +5,13 @@ |
package org.chromium.net.urlconnection; |
import java.io.IOException; |
+import java.io.InterruptedIOException; |
+import java.net.SocketTimeoutException; |
import java.util.concurrent.BlockingQueue; |
import java.util.concurrent.Executor; |
import java.util.concurrent.LinkedBlockingQueue; |
import java.util.concurrent.RejectedExecutionException; |
+import java.util.concurrent.TimeUnit; |
/** |
* A MessageLoop class for use in {@link CronetHttpURLConnection}. |
@@ -42,13 +45,54 @@ class MessageLoop implements Executor { |
} |
/** |
+ * Retrieves a task from the queue with the given timeout. |
+ * |
+ * @param useTimeout whether to use a timeout. |
+ * @param timeout Time to wait, in milliseconds. |
+ * @return A non-{@code null} Runnable from the queue. |
+ * @throws InterruptedIOException |
+ */ |
+ private Runnable take(boolean useTimeout, int timeout) throws InterruptedIOException { |
kapishnikov
2016/05/18 01:13:42
Should we change the timeout type in this method t
xunjieli
2016/05/18 13:31:27
Done.
|
+ Runnable task = null; |
+ try { |
+ if (!useTimeout) { |
+ task = mQueue.take(); // Blocks if the queue is empty. |
+ } else { |
+ // poll returns null upon timeout. |
+ task = mQueue.poll(timeout, TimeUnit.MILLISECONDS); |
+ } |
+ } catch (InterruptedException e) { |
+ InterruptedIOException exception = new InterruptedIOException(); |
+ exception.initCause(e); |
+ throw exception; |
+ } |
+ if (task == null) { |
+ // This will terminate the loop. |
+ throw new SocketTimeoutException(); |
+ } |
+ return task; |
+ } |
+ |
+ /** |
* Runs the message loop. Be sure to call {@link MessageLoop#quit()} |
* to end the loop. If an interruptedException occurs, the loop cannot be |
* started again (see {@link #mLoopFailed}). |
* @throws IOException |
*/ |
public void loop() throws IOException { |
+ loop(0); |
+ } |
+ |
+ /** |
+ * Runs the message loop. Be sure to call {@link MessageLoop#quit()} |
+ * to end the loop. If an interruptedException occurs, the loop cannot be |
+ * started again (see {@link #mLoopFailed}). |
+ * @param timeout Timeout, in milliseconds, or 0 for no timeout. |
+ * @throws IOException |
+ */ |
+ public void loop(int timeout) throws IOException { |
assert calledOnValidThread(); |
+ long start = System.currentTimeMillis(); |
kapishnikov
2016/05/18 01:13:43
It is better to use System.nanoTime(), which retur
xunjieli
2016/05/18 13:31:27
Done.
|
if (mLoopFailed) { |
throw new IllegalStateException( |
"Cannot run loop as an exception has occurred previously."); |
@@ -60,16 +104,24 @@ class MessageLoop implements Executor { |
mLoopRunning = true; |
while (mLoopRunning) { |
try { |
- Runnable task = mQueue.take(); // Blocks if the queue is empty. |
- task.run(); |
- } catch (InterruptedException | RuntimeException e) { |
+ if (timeout == 0) { |
+ take(false, timeout); |
kapishnikov
2016/05/18 01:13:42
Better take(false, 0)
xunjieli
2016/05/18 13:31:27
Done.
|
+ } else { |
+ long timeElapsed = System.currentTimeMillis() - start; |
+ // Make sure overflow won't happen when casting timeElapsed to an int. |
+ if (timeElapsed > timeout) { |
+ throw new SocketTimeoutException(); |
+ } |
+ // Will system clock run backwards? |
+ if (timeElapsed < 0) { |
kapishnikov
2016/05/18 01:13:42
This should not be possible with System.nanoTime()
xunjieli
2016/05/18 13:31:27
Done.
|
+ timeElapsed = 0; |
+ } |
+ take(true, timeout - (int) timeElapsed).run(); |
+ } |
+ } catch (InterruptedIOException | RuntimeException e) { |
mLoopRunning = false; |
mLoopFailed = true; |
- if (e instanceof InterruptedException) { |
- throw new IOException(e); |
- } else if (e instanceof RuntimeException) { |
- throw (RuntimeException) e; |
- } |
+ throw e; |
} |
} |
} |