package jetbrains.mps.core.tool.environment.common; /*Generated by MPS */ import java.util.List; import java.util.concurrent.Future; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.ArrayList; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ThreadPoolExecutor; import org.jetbrains.annotations.NonNls; import java.util.concurrent.TimeUnit; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ScheduledThreadPoolExecutor; /** * * @author cdr */ public class ConcurrencyUtil { public ConcurrencyUtil() { } /** * * invokes and waits all tasks using threadPool, avoiding thread starvation on the way * * @lookat http://gafter.blogspot.com/2006/11/thread-pool-puzzler.html */ public static <T> List<Future<T>> invokeAll(@NotNull Collection<Callable<T>> tasks, ExecutorService executorService) throws Throwable { if (executorService == null) { for (Callable<T> task : tasks) { task.call(); } return null; } List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); boolean done = false; try { for (Callable<T> t : tasks) { Future<T> future = executorService.submit(t); futures.add(future); } // force unstarted futures to execute using the current thread for (Future f : futures) { ((Runnable) f).run(); } for (Future f : futures) { try { f.get(); } catch (CancellationException ignore) { } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause != null) { throw cause; } } } done = true; } finally { if (!(done)) { for (Future f : futures) { f.cancel(false); } } } return futures; } /** * * @return defaultValue if there is no entry in the map (in that case defaultValue is placed into the map), or corresponding value if entry already exists */ @NotNull public static <K, V> V cacheOrGet(@NotNull ConcurrentMap<K, V> map, @NotNull final K key, @NotNull final V defaultValue) { V v = map.get(key); if (v != null) { return v; } V prev = map.putIfAbsent(key, defaultValue); return (prev == null ? defaultValue : prev); } @NotNull public static ThreadPoolExecutor newSingleThreadExecutor(@NotNull @NonNls final String threadFactoryName) { return ConcurrencyUtil.newSingleThreadExecutor(threadFactoryName, Thread.NORM_PRIORITY); } @NotNull public static ThreadPoolExecutor newSingleThreadExecutor(@NotNull final String threadFactoryName, final int threadPriority) { return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() { @Override public Thread newThread(final Runnable r) { final Thread thread = new Thread(r, threadFactoryName); thread.setPriority(threadPriority); return thread; } }); } @NotNull public static ScheduledThreadPoolExecutor newSingleScheduledThreadExecutor(@NotNull @NonNls final String threadFactoryName) { return ConcurrencyUtil.newSingleScheduledThreadExecutor(threadFactoryName, Thread.NORM_PRIORITY); } @NotNull public static ScheduledThreadPoolExecutor newSingleScheduledThreadExecutor(@NotNull final String threadFactoryName, final int threadPriority) { ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { @Override public Thread newThread(final Runnable r) { final Thread thread = new Thread(r, threadFactoryName); thread.setPriority(threadPriority); return thread; } }); executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); return executor; } }