package com.intellij.remoteServer.agent.impl.util; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Ref; import com.intellij.util.concurrency.Semaphore; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.LinkedBlockingQueue; /** * Created by IntelliJ IDEA. * User: michael.golubev */ public class SequentialTaskExecutor { private static final Logger LOG = Logger.getInstance("#" + SequentialTaskExecutor.class.getName()); private BlockingQueue<Runnable> myTasks; public SequentialTaskExecutor() { myTasks = new LinkedBlockingQueue<Runnable>(); ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { try { while (true) { Runnable task = myTasks.take(); task.run(); if (task instanceof FinalTask) { break; } } } catch (InterruptedException e) { LOG.debug(e); } } }); } public void queueTask(Runnable task) { myTasks.offer(task); } public <V> V queueAndWaitTask(final Callable<V> task) throws Throwable { final Ref<V> resultRef = new Ref<V>(); final Ref<Throwable> throwableRef = new Ref<Throwable>(); final Semaphore taskSemaphore = new Semaphore(); taskSemaphore.down(); queueTask(new Runnable() { @Override public void run() { try { resultRef.set(task.call()); } catch (Throwable e) { throwableRef.set(e); LOG.error(e); } finally { taskSemaphore.up(); } } }); taskSemaphore.waitFor(); if (!throwableRef.isNull()) { throw throwableRef.get(); } return resultRef.get(); } }