Skip to content

Commit

Permalink
Initial work on making resolver suitable for concurrent use - some ti…
Browse files Browse the repository at this point in the history
…dyup needed

git-svn-id: http://anonsvn.jboss.org/repos/weld/ri/trunk@394 1c488680-804c-0410-94cd-c6b725194a0e
  • Loading branch information
pmuir committed Dec 3, 2008
1 parent e7b50ed commit ee4dc4e
Showing 1 changed file with 133 additions and 35 deletions.
168 changes: 133 additions & 35 deletions webbeans-ri/src/main/java/org/jboss/webbeans/Resolver.java
Expand Up @@ -28,6 +28,11 @@
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

import javax.webbeans.NullableDependencyException;
import javax.webbeans.manager.Bean;
Expand Down Expand Up @@ -90,29 +95,28 @@ public String toString()

}

// TODO Why can't we generify Set?

/**
* Type safe map for caching annotation metadata
*/
@SuppressWarnings("unchecked")
private class AnnotatedItemMap extends ForwardingMap<AnnotatedItem<?, ?>, Set>
private class ConcurrentAnnotatedItemMap extends ForwardingMap<AnnotatedItem<?, ?>, Future>
{

private Map<AnnotatedItem<?, ?>, Set> delegate;
private Map<AnnotatedItem<?, ?>, Future> delegate;

public AnnotatedItemMap()
public ConcurrentAnnotatedItemMap()
{
delegate = new HashMap<AnnotatedItem<?, ?>, Set>();
delegate = new ConcurrentHashMap<AnnotatedItem<?, ?>, Future>();
}

public <T> Set<Bean<T>> get(AnnotatedItem<T, ?> key)
public <T> Future<Set<Bean<T>>> get(AnnotatedItem<T, ?> key)
{
return (Set<Bean<T>>) super.get(key);
return (Future<Set<Bean<T>>>) super.get(key);
}

@Override
protected Map<AnnotatedItem<?, ?>, Set> delegate()
protected Map<AnnotatedItem<?, ?>, Future > delegate()
{
return delegate;
}
Expand All @@ -125,18 +129,18 @@ public String toString()

}

private AnnotatedItemMap resolvedInjectionPoints;
private ConcurrentAnnotatedItemMap resolvedInjectionPoints;
private Set<AnnotatedItem<?, ?>> injectionPoints;

private Map<String, Set<Bean<?>>> resolvedNames;
private Map<String, Future<Set<Bean<?>>>> resolvedNames;

private ManagerImpl manager;

public Resolver(ManagerImpl manager)
{
this.manager = manager;
this.injectionPoints = new HashSet<AnnotatedItem<?, ?>>();
this.resolvedInjectionPoints = new AnnotatedItemMap();
this.resolvedInjectionPoints = new ConcurrentAnnotatedItemMap();
}

/**
Expand All @@ -147,20 +151,54 @@ public void addInjectionPoints(Collection<AnnotatedItem<?, ?>> elements)
{
injectionPoints.addAll(elements);
}

private void registerName(final String name)
{
FutureTask<Set<Bean<?>>> task = new FutureTask<Set<Bean<?>>>(new Callable<Set<Bean<?>>>()
{

public Set<Bean<?>> call() throws Exception
{
Set<Bean<?>> beans = new HashSet<Bean<?>>();
for (Bean<?> bean : manager.getBeans())
{
if ((bean.getName() == null && name == null) || (bean.getName() != null && bean.getName().equals(name)))
{
beans.add(bean);
}
}
return retainHighestPrecedenceBeans(beans, manager.getEnabledDeploymentTypes());
}

});
resolvedNames.put(name, task);

task.run();
}

private <T, S> void registerInjectionPoint(final AnnotatedItem<T, S> element)
{
Set<Bean<?>> beans = retainHighestPrecedenceBeans(getMatchingBeans(element, manager.getBeans(), manager.getMetaDataCache()), manager.getEnabledDeploymentTypes());
if (element.getType().isPrimitive())
FutureTask<Set<Bean<?>>> task = new FutureTask<Set<Bean<?>>>(new Callable<Set<Bean<?>>>()
{
for (Bean<?> bean : beans)

public Set<Bean<?>> call() throws Exception
{
if (bean.isNullable())
Set<Bean<?>> beans = retainHighestPrecedenceBeans(getMatchingBeans(element, manager.getBeans(), manager.getMetaDataCache()), manager.getEnabledDeploymentTypes());
if (element.getType().isPrimitive())
{
throw new NullableDependencyException("Primitive injection points resolves to nullable web bean");
for (Bean<?> bean : beans)
{
if (bean.isNullable())
{
throw new NullableDependencyException("Primitive injection points resolves to nullable web bean");
}
}
}
return beans;
}
}

});

resolvedInjectionPoints.put(new ResolvableAnnotatedItem<T, S>()
{

Expand All @@ -170,7 +208,9 @@ public AnnotatedItem<T, S> delegate()
return element;
}

}, beans);
}, task);

task.run();
}

/**
Expand All @@ -179,8 +219,8 @@ public AnnotatedItem<T, S> delegate()
*/
public void clear()
{
resolvedInjectionPoints = new AnnotatedItemMap();
resolvedNames = new HashMap<String, Set<Bean<?>>>();
resolvedInjectionPoints = new ConcurrentAnnotatedItemMap();
resolvedNames = new HashMap<String, Future<Set<Bean<?>>>>();
}

/**
Expand Down Expand Up @@ -214,7 +254,6 @@ public AnnotatedItem<T, S> delegate()

};

// TODO We don't need this I think
if (element.getType().equals(Object.class))
{
// TODO Fix this cast
Expand All @@ -226,7 +265,44 @@ public AnnotatedItem<T, S> delegate()
{
registerInjectionPoint(element);
}
beans = resolvedInjectionPoints.get(element);

boolean interupted = false;
try
{
while (true)
{
try
{
return Collections.unmodifiableSet(resolvedInjectionPoints.get(element).get());
}
catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
else if (e.getCause() instanceof Error)
{
throw (Error) e.getCause();
}
else
{
throw new IllegalStateException(e.getCause());
}
}
catch (InterruptedException e)
{
interupted = true;
}
}
}
finally
{
if (interupted)
{
Thread.currentThread().interrupt();
}
}
}
return Collections.unmodifiableSet(beans);
}
Expand All @@ -236,26 +312,48 @@ public AnnotatedItem<T, S> delegate()
*/
public Set<Bean<?>> get(String name)
{
Set<Bean<?>> beans;
if (resolvedNames.containsKey(name))
if (!resolvedNames.containsKey(name))
{
beans = resolvedNames.get(name);
registerName(name);
}
else

boolean interupted = false;
try
{
beans = new HashSet<Bean<?>>();
for (Bean<?> bean : manager.getBeans())
while (true)
{
if ((bean.getName() == null && name == null) || (bean.getName() != null && bean.getName().equals(name)))
try
{
return Collections.unmodifiableSet(resolvedNames.get(name).get());
}
catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
else if (e.getCause() instanceof Error)
{
throw (Error) e.getCause();
}
else
{
throw new IllegalStateException(e.getCause());
}
}
catch (InterruptedException e)
{
beans.add(bean);
interupted = true;
}
}
beans = retainHighestPrecedenceBeans(beans, manager.getEnabledDeploymentTypes());
resolvedNames.put(name, beans);

}
return Collections.unmodifiableSet(beans);
finally
{
if (interupted)
{
Thread.currentThread().interrupt();
}
}
}

private static Set<Bean<?>> retainHighestPrecedenceBeans(Set<Bean<?>> beans, List<Class<? extends Annotation>> enabledDeploymentTypes)
Expand Down Expand Up @@ -356,7 +454,7 @@ public String toString()
}
buffer.append("Resolved names: " + resolvedNames.size() + "\n");
i = 0;
for (Entry<String, Set<Bean<?>>> entry : resolvedNames.entrySet())
for (Entry<String, Future<Set<Bean<?>>>> entry : resolvedNames.entrySet())
{
buffer.append(++i + " - " + entry + ": " + entry.getValue().toString() + "\n");
}
Expand Down

0 comments on commit ee4dc4e

Please sign in to comment.