private static final class ExecutionSequencer.TaskNonReentrantExecutor extends java.util.concurrent.atomic.AtomicReference<ExecutionSequencer.RunningState> implements java.util.concurrent.Executor, java.lang.Runnable
MoreExecutors.directExecutor()
. Normally, when the first future completes, all the other
tasks would be called recursively. Here, we detect that the delegate executor is executing
inline, and maintain a queue to dispatch tasks iteratively. There is one instance of this class
per call to submit() or submitAsync(), and each instance supports only one call to execute().
This class would certainly be simpler and easier to reason about if it were built with ThreadLocal; however, ThreadLocal is not well optimized for the case where the ThreadLocal is non-static, and is initialized/removed frequently - this causes churn in the Thread specific hashmaps. Using a static ThreadLocal to avoid that overhead would mean that different ExecutionSequencer objects interfere with each other, which would be undesirable, in addition to increasing the memory footprint of every thread that interacted with it. In order to release entries in thread-specific maps when the ThreadLocal object itself is no longer referenced, ThreadLocal is usually implemented with a WeakReference, which can have negative performance properties; for example, calling WeakReference.get() on Android will block during an otherwise-concurrent GC cycle.
Modifier and Type | Field and Description |
---|---|
(package private) java.util.concurrent.Executor |
delegate
Executor the task was set to run on.
|
(package private) ExecutionSequencer |
sequencer
Used to update and read the latestTaskQueue field.
|
(package private) java.lang.Thread |
submitting
Thread that called execute().
|
(package private) java.lang.Runnable |
task
Set before calling delegate.execute(); set to null once run, so that it can be GCed; this
object may live on after, if submitAsync returns an incomplete future.
|
Modifier | Constructor and Description |
---|---|
private |
TaskNonReentrantExecutor(java.util.concurrent.Executor delegate,
ExecutionSequencer sequencer) |
Modifier and Type | Method and Description |
---|---|
void |
execute(java.lang.Runnable task) |
void |
run() |
private boolean |
trySetCancelled() |
private boolean |
trySetStarted() |
ExecutionSequencer sequencer
java.util.concurrent.Executor delegate
java.lang.Runnable task
java.lang.Thread submitting
private TaskNonReentrantExecutor(java.util.concurrent.Executor delegate, ExecutionSequencer sequencer)