11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.annotations.VisibleForTesting; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Preconditions; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executor; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Level; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Logger; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport javax.annotation.Nullable; 270888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport javax.annotation.concurrent.GuardedBy; 280888a09821a98ac0680fad765217302858e70fa4Paul Duffin 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>A list of listeners, each with an associated {@code Executor}, that 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * guarantees that every {@code Runnable} that is {@linkplain #add added} will 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be executed after {@link #execute()} is called. Any {@code Runnable} added 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * after the call to {@code execute} is still guaranteed to execute. There is no 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * guarantee, however, that listeners will be executed in the order that they 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * are added. 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Exceptions thrown by a listener will be propagated up to the executor. 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Any exception thrown during {@code Executor.execute} (e.g., a {@code 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * RejectedExecutionException} or an exception thrown by {@linkplain 403ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin * MoreExecutors#directExecutor direct execution}) will be caught and 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * logged. 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Nishant Thakkar 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Sven Mawson 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 1.0 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class ExecutionList { 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Logger to log exceptions caught when running runnables. 490888a09821a98ac0680fad765217302858e70fa4Paul Duffin @VisibleForTesting static final Logger log = Logger.getLogger(ExecutionList.class.getName()); 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 510888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 520888a09821a98ac0680fad765217302858e70fa4Paul Duffin * The runnable, executor pairs to execute. This acts as a stack threaded through the 530888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@link RunnableExecutorPair#next} field. 540888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 550888a09821a98ac0680fad765217302858e70fa4Paul Duffin @GuardedBy("this") 560888a09821a98ac0680fad765217302858e70fa4Paul Duffin private RunnableExecutorPair runnables; 570888a09821a98ac0680fad765217302858e70fa4Paul Duffin @GuardedBy("this") 580888a09821a98ac0680fad765217302858e70fa4Paul Duffin private boolean executed; 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** Creates a new, empty {@link ExecutionList}. */ 617dd252788645e940eada959bdde927426e2531c9Paul Duffin public ExecutionList() {} 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Adds the {@code Runnable} and accompanying {@code Executor} to the list of 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * listeners to execute. If execution has already begun, the listener is 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * executed immediately. 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Note: For fast, lightweight listeners that would be safe to execute in 693ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin * any thread, consider {@link MoreExecutors#directExecutor}. For heavier 703ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin * listeners, {@code directExecutor()} carries some caveats: First, the 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * thread that the listener runs in depends on whether the {@code 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * ExecutionList} has been executed at the time it is added. In particular, 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * listeners may run in the thread that calls {@code add}. Second, the thread 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that calls {@link #execute} may be an internal implementation thread, such 753ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin * as an RPC network thread, and {@code directExecutor()} listeners may 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * run in this thread. Finally, during the execution of a {@code 773ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin * directExecutor} listener, all other registered but unexecuted 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * listeners are prevented from running, even if those listeners are to run 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in other executors. 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void add(Runnable runnable, Executor executor) { 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Fail fast on a null. We throw NPE here because the contract of 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Executor states that it throws NPE on null listener, so we propagate 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // that contract up into the add method as well. 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Preconditions.checkNotNull(runnable, "Runnable was null."); 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Preconditions.checkNotNull(executor, "Executor was null."); 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Lock while we check state. We must maintain the lock while adding the 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // new pair so that another thread can't run the list out from under us. 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // We only add to the list if we have not yet started execution. 910888a09821a98ac0680fad765217302858e70fa4Paul Duffin synchronized (this) { 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!executed) { 930888a09821a98ac0680fad765217302858e70fa4Paul Duffin runnables = new RunnableExecutorPair(runnable, executor, runnables); 940888a09821a98ac0680fad765217302858e70fa4Paul Duffin return; 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Execute the runnable immediately. Because of scheduling this may end up 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // getting called before some of the previously added runnables, but we're 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // OK with that. If we want to change the contract to guarantee ordering 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // among runnables we'd have to modify the logic here to allow it. 1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin executeListener(runnable, executor); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Runs this execution list, executing all existing pairs in the order they 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * were added. However, note that listeners added after this point may be 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * executed before those previously added, and note that the execution order 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * of all listeners is ultimately chosen by the implementations of the 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * supplied executors. 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This method is idempotent. Calling it several times in parallel is 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * semantically equivalent to calling it exactly once. 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 (present in 1.0 as {@code run}) 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void execute() { 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Lock while we update our state so the add method above will finish adding 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // any listeners before we start to run them. 1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin RunnableExecutorPair list; 1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin synchronized (this) { 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (executed) { 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executed = true; 1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin list = runnables; 1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin runnables = null; // allow GC to free listeners even if this stays around for a while. 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin // If we succeeded then list holds all the runnables we to execute. The pairs in the stack are 1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin // in the opposite order from how they were added so we need to reverse the list to fulfill our 1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin // contract. 1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin // This is somewhat annoying, but turns out to be very fast in practice. Alternatively, we 1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin // could drop the contract on the method that enforces this queue like behavior since depending 1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin // on it is likely to be a bug anyway. 1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin // N.B. All writes to the list and the next pointers must have happened before the above 1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin // synchronized block, so we can iterate the list without the lock held here. 1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin RunnableExecutorPair reversedList = null; 1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin while (list != null) { 1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin RunnableExecutorPair tmp = list; 1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin list = list.next; 1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin tmp.next = reversedList; 1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin reversedList = tmp; 1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin while (reversedList != null) { 1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin executeListener(reversedList.runnable, reversedList.executor); 1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin reversedList = reversedList.next; 1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Submits the given runnable to the given {@link Executor} catching and logging all 1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@linkplain RuntimeException runtime exceptions} thrown by the executor. 1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin private static void executeListener(Runnable runnable, Executor executor) { 1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin try { 1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin executor.execute(runnable); 1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin } catch (RuntimeException e) { 1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Log it and keep going, bad runnable and/or executor. Don't 1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin // punish the other runnables if we're given a bad one. We only 1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin // catch RuntimeException because we want Errors to propagate up. 1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin log.log(Level.SEVERE, "RuntimeException while executing runnable " 1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin + runnable + " with executor " + executor, e); 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin private static final class RunnableExecutorPair { 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Runnable runnable; 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Executor executor; 1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Nullable RunnableExecutorPair next; 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin RunnableExecutorPair(Runnable runnable, Executor executor, RunnableExecutorPair next) { 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.runnable = runnable; 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.executor = executor; 1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin this.next = next; 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 178