race condition
authorAlexey Kudravtsev <cdr@intellij.com>
Fri, 25 Jun 2010 08:45:09 +0000 (12:45 +0400)
committerAlexey Kudravtsev <cdr@intellij.com>
Fri, 25 Jun 2010 08:46:41 +0000 (12:46 +0400)
platform/util/src/com/intellij/util/CommonProcessors.java
platform/util/src/com/intellij/util/UniqueResultsQuery.java

index d8144572a4de24d3e45309bfdec55f3dbf45cd00..7df83e71f77fe8dfc26e1c75e3bea0257c1a1fd6 100644 (file)
@@ -127,9 +127,18 @@ public class CommonProcessors {
       return false;
     }
   };
+  private static final Processor TRUE = new Processor<Object>() {
+    public boolean process(Object t) {
+      return true;
+    }
+  };
 
   @SuppressWarnings({"unchecked"})
   public static <T> Processor<T> alwaysFalse() {
     return FALSE;
   }
+  @SuppressWarnings({"unchecked"})
+  public static <T> Processor<T> alwaysTrue() {
+    return TRUE;
+  }
 }
index 577405af48951932d1be5e77a315b07a1ea9c2ee..2ec77b84d6068749c5a28f20a58bcd1e188c8d97 100644 (file)
@@ -21,8 +21,10 @@ import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * @author max
@@ -32,7 +34,7 @@ public class UniqueResultsQuery<T, M> implements Query<T> {
   private final TObjectHashingStrategy<M> myHashingStrategy;
   private final Function<T, M> myMapper;
 
-  public final static Function ID = new Function() {
+  public static final Function ID = new Function() {
     public Object fun(Object o) {
       return o;
     }
@@ -59,19 +61,33 @@ public class UniqueResultsQuery<T, M> implements Query<T> {
   }
 
   public boolean forEach(@NotNull final Processor<T> consumer) {
+    Collection<M> collection = process(consumer);
+    return collection != null;
+  }
+
+  // returns null if canceled
+  private Collection<M> process(final Processor<T> consumer) {
     final Set<M> processedElements = new ConcurrentHashSet<M>(myHashingStrategy);
-    return myOriginal.forEach(new Processor<T>() {
+    boolean success = myOriginal.forEach(new Processor<T>() {
       public boolean process(final T t) {
         return !processedElements.add(myMapper.fun(t)) || consumer.process(t);
       }
     });
+    return success ? processedElements : null;
   }
 
   @NotNull
   public Collection<T> findAll() {
-    final CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>();
-    forEach(processor);
-    return processor.getResults();
+    if (myMapper == ID) {
+      Collection<M> collection = process(CommonProcessors.<T>alwaysTrue());
+      //noinspection unchecked
+      return collection == null ? Collections.<T>emptyList() : (Collection<T>)collection;
+    }
+    else {
+      final CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>(new CopyOnWriteArrayList<T>());
+      forEach(processor);
+      return processor.getResults();
+    }
   }
 
   public T[] toArray(final T[] a) {