Skip to content

Commit f871b37

Browse files
committed
ObjectIndex: only resolve relevant pending objects
If a pending object will not be of a type compatible with the requested type, then skip resolution of that pending object. This improves performance of the get(Class) and getAll() methods in cases where there are a large number of pending objects in the index. It also helps to eliminate difficulties like those in issue #90.
1 parent e8e0f34 commit f871b37

File tree

1 file changed

+44
-4
lines changed

1 file changed

+44
-4
lines changed

src/main/java/org/scijava/object/ObjectIndex.java

+44-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131

3232
package org.scijava.object;
3333

34+
import java.lang.reflect.Method;
35+
import java.lang.reflect.ParameterizedType;
36+
import java.lang.reflect.Type;
3437
import java.util.ArrayList;
3538
import java.util.Collection;
3639
import java.util.Collections;
@@ -45,6 +48,7 @@
4548
import java.util.concurrent.ConcurrentHashMap;
4649

4750
import org.scijava.util.ClassUtils;
51+
import org.scijava.util.ConversionUtils;
4852

4953
/**
5054
* Data structure for managing lists of registered objects.
@@ -129,7 +133,7 @@ public List<E> getAll() {
129133
*/
130134
public List<E> get(final Class<?> type) {
131135
// lazily register any pending objects
132-
if (!pending.isEmpty()) resolvePending();
136+
if (!pending.isEmpty()) resolvePending(type);
133137

134138
List<E> list = retrieveList(type);
135139
// NB: Return a copy of the data, to facilitate thread safety.
@@ -380,15 +384,51 @@ protected List<E> retrieveList(final Class<?> type) {
380384
return list;
381385
}
382386

383-
private void resolvePending() {
387+
private void resolvePending(final Class<?> type) {
384388
synchronized (pending) {
385-
while (!pending.isEmpty()) {
386-
final LazyObjects<? extends E> c = pending.remove(0);
389+
for (int p = pending.size() - 1; p >= 0; p--) {
390+
final LazyObjects<? extends E> c = pending.get(p);
391+
392+
// NB: If this pending callback returns objects of a different
393+
// type than the one we are interested in, it can be skipped.
394+
if (!isCompatibleType(c, type)) continue;
395+
396+
// trigger the callback and add the results
397+
pending.remove(p);
387398
addAll(c.get());
388399
}
389400
}
390401
}
391402

403+
// -- Helper methods --
404+
405+
private boolean isCompatibleType(final LazyObjects<? extends E> c,
406+
final Class<?> type)
407+
{
408+
if (type == All.class) return true;
409+
410+
// extract the generic type from the LazyObjects#get return type
411+
final Method getMethod;
412+
try {
413+
getMethod = c.getClass().getMethod("get");
414+
}
415+
catch (final NoSuchMethodException exc) {
416+
throw new IllegalStateException(exc);
417+
}
418+
final Type returnType = getMethod.getGenericReturnType();
419+
if (returnType instanceof ParameterizedType) {
420+
final ParameterizedType pType = (ParameterizedType) returnType;
421+
final Type[] typeArgs = pType.getActualTypeArguments();
422+
if (typeArgs.length > 0 &&
423+
!type.isAssignableFrom(ConversionUtils.getClass(typeArgs[0])))
424+
{
425+
return false;
426+
}
427+
}
428+
429+
return true;
430+
}
431+
392432
// -- Helper classes --
393433

394434
private static class All {

0 commit comments

Comments
 (0)