/* * SerialExecutor.java * * Created on Mar 17, 2010, 5:52:02 PM * * Description: Provides a serial executor. * * Adapted from the example provided in the Javadoc for the java.util.concurrent.Executor class. * * Copyright (C) Mar 17, 2010 reed. * * This program is free software; you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.texai.util; import java.util.ArrayDeque; import java.util.Queue; import java.util.concurrent.Executor; import net.jcip.annotations.NotThreadSafe; /** Provides a serial executor. * * @author reed */ @NotThreadSafe public class SerialExecutor implements Executor { /** the tasks queue */ private final Queue<Runnable> tasks = new ArrayDeque<>(); /** the executor that serially executes the tasks */ private final Executor executor; /** the active task */ Runnable activeTask; /** Constructs a new SerialExecutor instance. * * @param executor the executor that serially executes the tasks */ public SerialExecutor(final Executor executor) { //Preconditions assert executor != null : "executor must not be null"; this.executor = executor; } /** Executes the given command at some time in the future. * * @param task the runnable task */ @Override public synchronized void execute(final Runnable task) { //Preconditions assert task != null : "task must not be null"; tasks.offer((Runnable) new Runnable() { @Override public void run() { try { task.run(); } finally { scheduleNext(); } } }); if (activeTask == null) { scheduleNext(); } } /** Schedules the next task. */ private synchronized void scheduleNext() { activeTask = tasks.poll(); if (activeTask != null) { executor.execute(activeTask); } } }