Use ConcurrentHashMap to cache fetchers, on platforms that support it.

This commit is contained in:
Michael Bayne
2012-10-01 09:27:36 -07:00
parent 41eec508cb
commit 5ec24e947c
4 changed files with 30 additions and 17 deletions
@@ -3,6 +3,8 @@
package com.samskivert.mustache;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -11,6 +13,7 @@ import java.util.Map;
*/
public class BasicCollector implements Mustache.Collector
{
@Override
public Iterator<?> toIterator (final Object value) {
if (value instanceof Iterable<?>) {
return ((Iterable<?>)value).iterator();
@@ -21,8 +24,8 @@ public class BasicCollector implements Mustache.Collector
return null;
}
public Mustache.VariableFetcher createFetcher (Object ctx, String name)
{
@Override
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
// support both .name and this.name to fetch members
if (name == Template.DOT_NAME || name == Template.THIS_NAME) {
return THIS_FETCHER;
@@ -35,6 +38,11 @@ public class BasicCollector implements Mustache.Collector
return null;
}
@Override
public <K,V> Map<K,V> createFetcherCache () {
return Collections.synchronizedMap(new HashMap<K,V>());
}
protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() {
public Object get (Object ctx, String name) throws Exception {
return ((Map<?,?>)ctx).get(name);
@@ -9,6 +9,8 @@ import java.lang.reflect.Method;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* The default collector used by JMustache.
@@ -34,8 +36,7 @@ public class DefaultCollector extends BasicCollector
}
@Override
public Mustache.VariableFetcher createFetcher (Object ctx, String name)
{
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);
if (fetcher != null) return fetcher;
@@ -61,8 +62,12 @@ public class DefaultCollector extends BasicCollector
return null;
}
protected Method getMethod (Class<?> clazz, String name)
{
@Override
public <K,V> Map<K,V> createFetcherCache () {
return new ConcurrentHashMap<K,V>();
}
protected Method getMethod (Class<?> clazz, String name) {
Method m;
try {
m = clazz.getDeclaredMethod(name);
@@ -95,8 +100,7 @@ public class DefaultCollector extends BasicCollector
return null;
}
protected Field getField (Class<?> clazz, String name)
{
protected Field getField (Class<?> clazz, String name) {
Field f;
try {
f = clazz.getDeclaredField(name);
@@ -11,6 +11,7 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Provides <a href="http://mustache.github.com/">Mustache</a> templating services.
@@ -160,6 +161,11 @@ public class Mustache
* never be null. The fetcher will be cached and reused for future contexts for which
* {@code octx.getClass().equals(nctx.getClass()}. */
VariableFetcher createFetcher (Object ctx, String name);
/** Creates a map to be used to cache {@link VariableFetcher} instances. The GWT-compatible
* collector returns a HashMap here, but the reflection based fetcher (which only works on
* the JVM and Android, returns a concurrent hashmap. */
<K,V> Map<K,V> createFetcherCache ();
}
/**
@@ -73,6 +73,7 @@ public class Template
{
_segs = segs;
_compiler = compiler;
_fcache = _compiler.collector.createFetcherCache();
}
protected void executeSegs (Context ctx, Writer out) throws MustacheException
@@ -190,10 +191,7 @@ public class Template
}
Key key = new Key(data.getClass(), name);
Mustache.VariableFetcher fetcher;
synchronized (_fcache) {
fetcher = _fcache.get(key);
}
Mustache.VariableFetcher fetcher = _fcache.get(key);
if (fetcher != null) {
try {
return fetcher.get(data, name);
@@ -213,9 +211,7 @@ public class Template
try {
Object value = fetcher.get(data, name);
synchronized (_fcache) {
_fcache.put(key, fetcher);
}
_fcache.put(key, fetcher);
return value;
} catch (Exception e) {
throw new MustacheException(
@@ -236,8 +232,7 @@ public class Template
protected final Segment[] _segs;
protected final Mustache.Compiler _compiler;
protected final Map<Key, Mustache.VariableFetcher> _fcache =
new HashMap<Key, Mustache.VariableFetcher>();
protected final Map<Key, Mustache.VariableFetcher> _fcache;
protected static class Context
{