/* * $Id$ * * Copyright (c) 2009 by Joel Uckelman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.tools.concurrent; import VASSAL.tools.lang.Pair; /** * A {@link Runnable} which operates on a rolling range. * * A {@code RangedRunnable} can be updated after it has been submitted but * before it has been run. This cuts down on the number of times the * {@code RangedRunnable} must be submitted, and is appropriate for values * where only the most recent update matters. * * @param <T> the type of the lower and upper bounds in the range * @author Joel Uckelman * @since 3.1.11 */ public abstract class RangedRunnable<T> implements Runnable { protected Pair<T,T> range; protected boolean submitted = false; /** * Creates a new {@code RangedRunnable} with the given lower bound. * * @param init the initial lower bound */ public RangedRunnable(T init) { range = new Pair<T,T>(init, null); } /** * {@inheritDoc} * * <p>Flushes the range and calls {@see #run(Pair<T,T>)}.</p> */ public final void run() { run(flush()); } /** * Sets the value of the upper end of the range. * * @param last the value to set * @param submit whether to also submit the change */ public final synchronized void setLast(T last, boolean submit) { if (last != range.second) { range = new Pair<T,T>(range.first, last); } if (submit && !submitted) { submit(); submitted = true; } } /** * Hands the {@code RangedRunnable} off to be executed. * * <p>This method may be executed only from {@see #setLast}.</p> */ protected abstract void submit(); /** * Processes the given range. * * @param r the range to process */ protected abstract void run(Pair<T,T> r); /** * Returns the old range and creates a new range adjacent to the old one. * The upper bound of the old range becomes the lower bound of the new range. * * @return the range being flushed */ private final synchronized Pair<T,T> flush() { final Pair<T,T> flushed = range; range = new Pair<T,T>(flushed.second, null); submitted = false; return flushed; } }