Class ExecutionSequencer.TaskNonReentrantExecutor

  • All Implemented Interfaces:
    java.io.Serializable, java.lang.Runnable, java.util.concurrent.Executor
    Enclosing class:
    ExecutionSequencer

    private static final class ExecutionSequencer.TaskNonReentrantExecutor
    extends java.util.concurrent.atomic.AtomicReference<ExecutionSequencer.RunningState>
    implements java.util.concurrent.Executor, java.lang.Runnable
    This class helps avoid a StackOverflowError when large numbers of tasks are submitted with 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.

    • Field Summary

      Fields 
      Modifier and Type Field 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.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void execute​(java.lang.Runnable task)  
      void run()  
      private boolean trySetCancelled()  
      private boolean trySetStarted()  
      • Methods inherited from class java.util.concurrent.atomic.AtomicReference

        accumulateAndGet, compareAndExchange, compareAndExchangeAcquire, compareAndExchangeRelease, compareAndSet, get, getAcquire, getAndAccumulate, getAndSet, getAndUpdate, getOpaque, getPlain, lazySet, set, setOpaque, setPlain, setRelease, toString, updateAndGet, weakCompareAndSet, weakCompareAndSetAcquire, weakCompareAndSetPlain, weakCompareAndSetRelease, weakCompareAndSetVolatile
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • sequencer

        ExecutionSequencer sequencer
        Used to update and read the latestTaskQueue field. Set to null once the runnable has been run or queued.
      • delegate

        java.util.concurrent.Executor delegate
        Executor the task was set to run on. Set to null when the task has been queued, run, or cancelled.
      • task

        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.
      • submitting

        java.lang.Thread submitting
        Thread that called execute(). Set in execute, cleared when delegate.execute() returns.
    • Constructor Detail

      • TaskNonReentrantExecutor

        private TaskNonReentrantExecutor​(java.util.concurrent.Executor delegate,
                                         ExecutionSequencer sequencer)
    • Method Detail

      • execute

        public void execute​(java.lang.Runnable task)
        Specified by:
        execute in interface java.util.concurrent.Executor
      • run

        public void run()
        Specified by:
        run in interface java.lang.Runnable
      • trySetStarted

        private boolean trySetStarted()
      • trySetCancelled

        private boolean trySetCancelled()