blob: 052cad6a403f0ffc3152202f5a016eefb0a67f29 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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 com.intellij.openapi.progress;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayDeque;
import java.util.Queue;
@SomeQueue
public abstract class AbstractTaskQueue<T> {
private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.AbstractTaskQueue");
private final Object myLock;
private final Queue<T> myQueue;
private boolean myActive;
protected final Runnable myQueueWorker;
public AbstractTaskQueue() {
myLock = new Object();
myQueue = new ArrayDeque<T>();
myActive = false;
myQueueWorker = new MyWorker();
}
/**
* !!! done under lock! (to allow single failures when putting into the execution queue)
* Should run {@link #myQueueWorker}
*/
protected abstract void runMe();
protected abstract void runStuff(T stuff);
public void run(@NotNull final T stuff) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
runStuff(stuff);
return;
}
synchronized (myLock) {
try {
myQueue.add(stuff);
if (! myActive) {
runMe();
}
} catch (Throwable t) {
LOG.info(t);
throw t instanceof RuntimeException ? ((RuntimeException) t) : new RuntimeException(t);
} finally {
myActive = true;
}
}
}
private class MyWorker implements Runnable {
public void run() {
while (true) {
try {
final T stuff;
synchronized (myLock) {
stuff = myQueue.poll();
}
if (stuff != null) {
// each task is executed only once, once it has been taken from the queue..
runStuff(stuff);
}
} catch (Throwable t) {
LOG.info(t);
} finally {
synchronized (myLock) {
if (myQueue.isEmpty()) {
myActive = false;
return;
}
}
}
}
}
}
}