/** * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.waveprotocol.wave.testing; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.Semaphore; /** * A executor which defers execution until requested. * * This class is designed to be used as an in-thread fake of an executor, and is * not thread safe. * * @author anorth@google.com (Alex North) */ public final class DeferredExecutor implements Executor { private final Semaphore numTasks = new Semaphore(0); private List<Runnable> thingsToExecute = Lists.newArrayList(); private boolean shutdownCalled = false; @Override public void execute(Runnable command) throws RejectedExecutionException { if (shutdownCalled) { throw new RejectedExecutionException(); } thingsToExecute.add(command); numTasks.release(); } public List<Runnable> shutdown() { shutdownCalled = true; runQueuedCommands(); List<Runnable> unexecuted = Lists.newArrayList(thingsToExecute); thingsToExecute.clear(); return unexecuted; } public boolean isShutdown() { return shutdownCalled; } public void checkShutdown() { Preconditions.checkState(isShutdown(), "Not shut down"); Preconditions.checkState(thingsToExecute.size() == 0, "Still has things to execute"); } /** * Runs all commands which have been scheduled and removes them from the * queue. Commands are executed in the calling thread. * * Note that commands scheduled as a result of executed commands are not * immediately run. * * @see #runAllCommands */ public void runQueuedCommands() { List<Runnable> thingsToExecuteNow = thingsToExecute; thingsToExecute = new ArrayList<Runnable>(); for (Runnable r : thingsToExecuteNow) { r.run(); } } /** * Runs commands until no commands remain to run. */ public void runAllCommands() { while (!thingsToExecute.isEmpty()) { runQueuedCommands(); } } /** * Waits for howMany tasks to be submitted. */ public void waitForTasks(int howMany) { numTasks.acquireUninterruptibly(howMany); } }