| Index: components/cronet/android/api/src/org/chromium/net/DirectPreventingExecutor.java
|
| diff --git a/components/cronet/android/api/src/org/chromium/net/DirectPreventingExecutor.java b/components/cronet/android/api/src/org/chromium/net/DirectPreventingExecutor.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..798d1c91162b305f19bd98ae36378597d56af403
|
| --- /dev/null
|
| +++ b/components/cronet/android/api/src/org/chromium/net/DirectPreventingExecutor.java
|
| @@ -0,0 +1,56 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.net;
|
| +
|
| +import java.util.concurrent.Executor;
|
| +
|
| +/**
|
| + * Executor that detects and throws if its mDelegate runs a submitted runnable inline.
|
| + */
|
| +final class DirectPreventingExecutor implements Executor {
|
| + private final Executor mDelegate;
|
| +
|
| + DirectPreventingExecutor(Executor delegate) {
|
| + this.mDelegate = delegate;
|
| + }
|
| +
|
| + @Override
|
| + public void execute(Runnable command) {
|
| + Thread currentThread = Thread.currentThread();
|
| + InlineCheckingRunnable runnable = new InlineCheckingRunnable(command, currentThread);
|
| + mDelegate.execute(runnable);
|
| + if (runnable.mExecutedInline != null) {
|
| + throw runnable.mExecutedInline;
|
| + } else {
|
| + // It's possible that this method is being called on an executor, and the runnable that
|
| + // was just queued will run on this thread after the current runnable returns. By
|
| + // nulling out the mCallingThread field, the InlineCheckingRunnable's current thread
|
| + // comparison will not fire.
|
| + runnable.mCallingThread = null;
|
| + }
|
| + }
|
| +
|
| + private static final class InlineCheckingRunnable implements Runnable {
|
| + private final Runnable mCommand;
|
| + private Thread mCallingThread;
|
| + private InlineExecutionProhibitedException mExecutedInline = null;
|
| +
|
| + private InlineCheckingRunnable(Runnable command, Thread callingThread) {
|
| + this.mCommand = command;
|
| + this.mCallingThread = callingThread;
|
| + }
|
| +
|
| + @Override
|
| + public void run() {
|
| + if (Thread.currentThread() == mCallingThread) {
|
| + // Can't throw directly from here, since the delegate executor could catch this
|
| + // exception.
|
| + mExecutedInline = new InlineExecutionProhibitedException();
|
| + return;
|
| + }
|
| + mCommand.run();
|
| + }
|
| + }
|
| +}
|
|
|