Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.net.urlconnection; | |
| 6 | |
| 7 import java.io.IOException; | |
| 8 import java.util.concurrent.BlockingQueue; | |
| 9 import java.util.concurrent.Executor; | |
| 10 import java.util.concurrent.LinkedBlockingQueue; | |
| 11 import java.util.concurrent.RejectedExecutionException; | |
| 12 | |
| 13 /** | |
| 14 * A MessageLoop class for use in {@link CronetHttpURLConnection}. | |
| 15 */ | |
| 16 public final class MessageLoop implements Executor { | |
| 17 private final BlockingQueue<Runnable> mQueue; | |
| 18 | |
| 19 // A reusable runnable to quit the message loop. | |
| 20 private final Runnable mQuitTask; | |
| 21 | |
| 22 // Indicates whether this message loop is currently running. | |
| 23 private boolean mLoopRunning = false; | |
| 24 | |
| 25 // Indicates whether waiting for task has been interrupted. The loop cannot | |
| 26 // be safely started if it has been interrupted. Because this might cause | |
| 27 // the loop to terminate immediately if there is a quit task enqueued. | |
| 28 private boolean mWaitingInterrupted = false; | |
| 29 | |
| 30 public MessageLoop() { | |
| 31 mQueue = new LinkedBlockingQueue<Runnable>(); | |
| 32 mQuitTask = new Runnable() { | |
| 33 @Override | |
| 34 public void run() { | |
| 35 mLoopRunning = false; | |
| 36 } | |
| 37 }; | |
| 38 } | |
| 39 | |
| 40 /** | |
| 41 * Runs the message loop. Be sure to call {@link MessageLoop#postQuitTask()} | |
| 42 * to end the loop. If an interruptedException occurs, the loop cannot be | |
| 43 * started again (see {@link #mWaitingInterrupted}). | |
| 44 * @throws IOException | |
| 45 */ | |
| 46 public void loop() throws IOException { | |
| 47 if (mWaitingInterrupted) { | |
| 48 throw new IllegalStateException( | |
| 49 "Cannot run loop as the loop has been terminated."); | |
| 50 } | |
| 51 if (mLoopRunning) { | |
| 52 throw new IllegalStateException( | |
| 53 "Cannot run loop when it is already running."); | |
| 54 } | |
| 55 mLoopRunning = true; | |
| 56 while (mLoopRunning) { | |
| 57 try { | |
| 58 Runnable task = mQueue.take(); // Blocks if the queue is empty. | |
| 59 task.run(); | |
| 60 } catch (InterruptedException | RuntimeException e) { | |
| 61 mLoopRunning = false; | |
| 62 if (e instanceof InterruptedException) { | |
| 63 mWaitingInterrupted = true; | |
| 64 throw new IOException(e); | |
| 65 } else if (e instanceof RuntimeException) { | |
|
xunjieli
2014/12/03 19:03:30
Not sure if this is what you have in mind..
mmenke
2014/12/03 20:05:39
I'd like to prevent running the loop again here, t
xunjieli
2014/12/03 20:46:52
Done. I added a new test for this as well.
| |
| 66 throw (RuntimeException) e; | |
| 67 } | |
| 68 } | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 /** | |
| 73 * Posts a reusable runnable, {@link #mQuitTask} to quit the loop. This | |
| 74 * causes the {@link #loop()} to stop after processing all currently | |
| 75 * enqueued messages. | |
| 76 */ | |
| 77 public void postQuitTask() { | |
| 78 execute(mQuitTask); | |
| 79 } | |
| 80 | |
| 81 /** | |
| 82 * Posts a task to the message loop. | |
| 83 */ | |
| 84 @Override | |
| 85 public void execute(Runnable task) throws RejectedExecutionException { | |
| 86 if (task == null) { | |
| 87 throw new IllegalArgumentException(); | |
| 88 } | |
| 89 try { | |
| 90 mQueue.put(task); | |
| 91 } catch (InterruptedException e) { | |
| 92 // In theory this exception won't happen, since we have an blocking | |
| 93 // queue with Integer.MAX_Value, put() call will not block. | |
| 94 throw new RejectedExecutionException(e); | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 /** | |
| 99 * Returns whether the loop is currently running. Used in testing. | |
| 100 */ | |
| 101 public boolean isRunning() { | |
| 102 return mLoopRunning; | |
| 103 } | |
| 104 | |
| 105 /** | |
| 106 * Returns whether waiting for a task has been interrupted. Used in testing. | |
| 107 */ | |
| 108 public boolean isWaitingInterrupted() { | |
| 109 return mWaitingInterrupted; | |
| 110 } | |
| 111 } | |
| OLD | NEW |