Chromium Code Reviews| 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; |
| } |
| } |
| } |