/*
* RapidMiner
*
* Copyright (C) 2001-2011 by Rapid-I and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapid-i.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.tools;
import java.util.logging.Level;
import com.rapidminer.tools.LogService;
/** A queue of runnables in which only execution of the last is relevant.
* Older runnables become obsolete as soon as a new is inserted.
*
* @author Simon Fischer
*
*/
public class UpdateQueue extends Thread {
private Runnable pending;
public UpdateQueue(String name) {
super("UpdateQueue-"+name);
setDaemon(true);
}
private Object lock = new Object();
private boolean shutdownRequested = false;
/** Queues runnable for execution. Will be executed as soon as the current
* runnable has terminated. If there is no current executable, will be
* executed immediately (in the thread created by this instance).
* If this method is called again before the current runnable is executed,
* runnable will be discarded in favor of the new. */
public void execute(Runnable runnable) {
synchronized (lock) {
pending = runnable;
lock.notifyAll();
}
}
/** Executes the given progress thread and waits for it, so only one will be
* enqueued at a time. (The calling thread will *not* wait, only the queue waits! */
public void executeBackgroundJob(final ProgressThread progressThread) {
execute(new Runnable() {
@Override
public void run() {
progressThread.startAndWait();
}
});
}
@Override
public void run() {
while (!shutdownRequested ) {
final Runnable target;
synchronized (lock) {
target = pending;
pending = null;
}
if (target != null) {
try {
target.run();
} catch (Exception e) {
LogService.getRoot().log(Level.WARNING, "Error executing task in "+getName()+": "+e, e);
}
}
synchronized (lock) {
if (pending == null) {
try {
lock.wait();
} catch (InterruptedException e) { }
}
}
}
}
public void shutdown() {
synchronized (lock) {
pending = null;
shutdownRequested = true;
lock.notifyAll();
}
}
}