diff --git a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java index 3c75ce99102c..61d559ec8f5e 100644 --- a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java +++ b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java @@ -15,6 +15,7 @@ */ package com.intellij.util.concurrency; +import com.intellij.Patches; import com.intellij.diagnostic.ThreadDumper; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; @@ -113,7 +114,7 @@ public class BoundedTaskExecutor extends AbstractExecutorService { if (isShutdown()) { throw new RejectedExecutionException("Already shutdown"); } - long status = myStatus.addAndGet(1 + (1L << 32)); // increment inProgress and queue stamp atomically + long status = incrementCounterAndTimestamp(); // increment inProgress and queue stamp atomically if (tryToExecute(status, task)) { return; @@ -124,6 +125,20 @@ public class BoundedTaskExecutor extends AbstractExecutorService { pollAndExecute(status); } + static { + assert Patches.USE_REFLECTION_TO_ACCESS_JDK8; + } + // todo replace with myStatus.getAndUpdate() + private long incrementCounterAndTimestamp() { + long status; + long newStatus; + do { + status = myStatus.get(); + newStatus = status + 1 + (1L << 32) & 0x7fffffffffffffffL; + } while (!myStatus.compareAndSet(status, newStatus)); + return newStatus; + } + private void pollAndExecute(long status) { while (true) { int inProgress = (int)status; @@ -239,8 +254,7 @@ public class BoundedTaskExecutor extends AbstractExecutorService { public String toString() { return "BoundedExecutor(" + myMaxTasks + ") " + (isShutdown() ? "SHUTDOWN " : "") + "inProgress: " + (int)myStatus.get() + - "; " + myTaskQueue.size() + - " tasks in queue: [" + ContainerUtil.map(myTaskQueue, new Function() { + "; " + myTaskQueue.size() + " tasks in queue: [" + ContainerUtil.map(myTaskQueue, new Function() { @Override public Object fun(Runnable runnable) { return info(runnable);