diff --git a/java/java-analysis-impl/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java b/java/java-analysis-impl/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java index b32d3c579243..4d60d0fab667 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java @@ -88,7 +88,9 @@ public final class WhileLoopSpinsOnFieldInspection extends BaseInspection { final PsiExpression condition = statement.getCondition(); final PsiField field = getFieldIfSimpleFieldComparison(condition); if (field == null) return; - if (body != null && (VariableAccessUtils.variableIsAssigned(field, body) || containsCall(body, ThreadingUtils::isWaitCall))) { + if (body != null && + (VariableAccessUtils.variableIsAssigned(field, body) || + containsCall(body, expression -> ThreadingUtils.isWaitCall(expression) || ThreadingUtils.isAwaitCall(expression)))) { return; } boolean java9 = PsiUtil.isLanguageLevel9OrHigher(field); diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/threading/while_loop_spins_on_field/ConditionBoundedBuffer.java b/java/java-tests/testData/ig/com/siyeh/igtest/threading/while_loop_spins_on_field/ConditionBoundedBuffer.java new file mode 100644 index 000000000000..570d9e532841 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igtest/threading/while_loop_spins_on_field/ConditionBoundedBuffer.java @@ -0,0 +1,55 @@ +package com.siyeh.igtest.threading.while_loop_spins_on_field; + +import java.util.concurrent.locks.*; + +/** + * ConditionBoundedBuffer + *

+ * Bounded buffer using explicit condition variables + * + * @author Brian Goetz and Tim Peierls + */ +public class ConditionBoundedBuffer { + protected final Lock lock = new ReentrantLock(); + // CONDITION PREDICATE: notFull (count < items.length) + private final Condition notFull = lock.newCondition(); + // CONDITION PREDICATE: notEmpty (count > 0) + private final Condition notEmpty = lock.newCondition(); + private static final int BUFFER_SIZE = 100; + private final T[] items = (T[]) new Object[BUFFER_SIZE]; + private int tail, head, count; + + // BLOCKS-UNTIL: notFull + public void put(T x) throws InterruptedException { + lock.lock(); + try { + while (count == items.length) + notFull.await(); + items[tail] = x; + if (++tail == items.length) + tail = 0; + ++count; + notEmpty.signal(); + } finally { + lock.unlock(); + } + } + + // BLOCKS-UNTIL: notEmpty + public T take() throws InterruptedException { + lock.lock(); + try { + while (count == 0) + notEmpty.await(); + T x = items[head]; + items[head] = null; + if (++head == items.length) + head = 0; + --count; + notFull.signal(); + return x; + } finally { + lock.unlock(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspectionTest.java b/java/java-tests/testSrc/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspectionTest.java index fe7ecef28040..8846a856e9e2 100644 --- a/java/java-tests/testSrc/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspectionTest.java +++ b/java/java-tests/testSrc/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspectionTest.java @@ -16,6 +16,12 @@ public class WhileLoopSpinsOnFieldInspectionTest extends LightJavaInspectionTest IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_8, this::doTest); } + public void testConditionBoundedBuffer() { + // Sample from JCIP + // See IDEA-364908 + doTest(); + } + public void testMultiFileFix() { myFixture.addFileToProject("F1.java", """ public class F1 {