package jetbrains.mps.debugger.java.runtime.engine.concurrent;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.CountDownLatch;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import org.apache.log4j.Level;
public class ManagerThread {
private static final Logger LOG = LogManager.getLogger(ManagerThread.class);
private final BlockingQueue<IManagerCommand> myCommandQueue = new LinkedBlockingQueue<IManagerCommand>();
private final ManagerThread.WorkerThread myThread = new ManagerThread.WorkerThread();
private volatile boolean myClosed = false;
public ManagerThread() {
myThread.start();
}
public void invoke(IManagerCommand command) {
if (isManagerThread()) {
myThread.processCommand(command);
} else {
schedule(command);
}
}
public void invokeAndWait(final IManagerCommand command) {
if (isManagerThread()) {
myThread.processCommand(command);
} else {
final CountDownLatch countDown = new CountDownLatch(1);
schedule(Commands.fromClosure(new _FunctionTypes._void_P0_E0() {
public void invoke() {
try {
command.invoke();
} finally {
countDown.countDown();
}
}
}, new _FunctionTypes._void_P0_E0() {
public void invoke() {
try {
command.cancel();
} finally {
countDown.countDown();
}
}
}));
try {
countDown.await();
} catch (InterruptedException ignore) {
}
}
}
public void schedule(IManagerCommand command) {
if (myClosed) {
command.cancel();
} else {
myCommandQueue.offer(command);
}
}
public void close() {
myClosed = true;
}
public static boolean isManagerThread() {
return Thread.currentThread() instanceof ManagerThread.WorkerThread;
}
public static void assertIsMangerThread() {
assert isManagerThread();
}
private class WorkerThread extends Thread {
public WorkerThread() {
}
@Override
public void run() {
try {
while (true) {
if (isInterrupted() || myClosed) {
break;
}
processCommand(myCommandQueue.take());
}
if (myClosed) {
List<IManagerCommand> unprocessed = ListSequence.fromList(new ArrayList<IManagerCommand>());
myCommandQueue.drainTo(unprocessed);
for (IManagerCommand command : ListSequence.fromList(unprocessed)) {
try {
command.cancel();
} catch (Throwable t) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("Command " + command + " threw an exception.", t);
}
}
}
}
} catch (InterruptedException ignore) {
// do what?
}
if (LOG.isDebugEnabled()) {
LOG.debug("Thread " + this + " finished working.");
}
}
private void processCommand(IManagerCommand command) {
try {
if (myClosed) {
command.cancel();
} else {
command.invoke();
}
} catch (Throwable t) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("Command " + command + " threw an exception.", t);
}
}
}
}
}