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; package com.samskivert.mustache;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@@ -11,6 +13,7 @@ import java.util.Map;
*/ */
public class BasicCollector implements Mustache.Collector public class BasicCollector implements Mustache.Collector
{ {
@Override
public Iterator<?> toIterator (final Object value) { public Iterator<?> toIterator (final Object value) {
if (value instanceof Iterable<?>) { if (value instanceof Iterable<?>) {
return ((Iterable<?>)value).iterator(); return ((Iterable<?>)value).iterator();
@@ -21,8 +24,8 @@ public class BasicCollector implements Mustache.Collector
return null; 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 // support both .name and this.name to fetch members
if (name == Template.DOT_NAME || name == Template.THIS_NAME) { if (name == Template.DOT_NAME || name == Template.THIS_NAME) {
return THIS_FETCHER; return THIS_FETCHER;
@@ -35,6 +38,11 @@ public class BasicCollector implements Mustache.Collector
return null; 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() { protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() {
public Object get (Object ctx, String name) throws Exception { public Object get (Object ctx, String name) throws Exception {
return ((Map<?,?>)ctx).get(name); return ((Map<?,?>)ctx).get(name);
@@ -9,6 +9,8 @@ import java.lang.reflect.Method;
import java.util.AbstractList; import java.util.AbstractList;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* The default collector used by JMustache. * The default collector used by JMustache.
@@ -34,8 +36,7 @@ public class DefaultCollector extends BasicCollector
} }
@Override @Override
public Mustache.VariableFetcher createFetcher (Object ctx, String name) public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
{
Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name); Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);
if (fetcher != null) return fetcher; if (fetcher != null) return fetcher;
@@ -61,8 +62,12 @@ public class DefaultCollector extends BasicCollector
return null; 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; Method m;
try { try {
m = clazz.getDeclaredMethod(name); m = clazz.getDeclaredMethod(name);
@@ -95,8 +100,7 @@ public class DefaultCollector extends BasicCollector
return null; return null;
} }
protected Field getField (Class<?> clazz, String name) protected Field getField (Class<?> clazz, String name) {
{
Field f; Field f;
try { try {
f = clazz.getDeclaredField(name); f = clazz.getDeclaredField(name);
@@ -11,6 +11,7 @@ import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Provides <a href="http://mustache.github.com/">Mustache</a> templating services. * 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 * never be null. The fetcher will be cached and reused for future contexts for which
* {@code octx.getClass().equals(nctx.getClass()}. */ * {@code octx.getClass().equals(nctx.getClass()}. */
VariableFetcher createFetcher (Object ctx, String name); 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; _segs = segs;
_compiler = compiler; _compiler = compiler;
_fcache = _compiler.collector.createFetcherCache();
} }
protected void executeSegs (Context ctx, Writer out) throws MustacheException protected void executeSegs (Context ctx, Writer out) throws MustacheException
@@ -190,10 +191,7 @@ public class Template
} }
Key key = new Key(data.getClass(), name); Key key = new Key(data.getClass(), name);
Mustache.VariableFetcher fetcher; Mustache.VariableFetcher fetcher = _fcache.get(key);
synchronized (_fcache) {
fetcher = _fcache.get(key);
}
if (fetcher != null) { if (fetcher != null) {
try { try {
return fetcher.get(data, name); return fetcher.get(data, name);
@@ -213,9 +211,7 @@ public class Template
try { try {
Object value = fetcher.get(data, name); Object value = fetcher.get(data, name);
synchronized (_fcache) { _fcache.put(key, fetcher);
_fcache.put(key, fetcher);
}
return value; return value;
} catch (Exception e) { } catch (Exception e) {
throw new MustacheException( throw new MustacheException(
@@ -236,8 +232,7 @@ public class Template
protected final Segment[] _segs; protected final Segment[] _segs;
protected final Mustache.Compiler _compiler; protected final Mustache.Compiler _compiler;
protected final Map<Key, Mustache.VariableFetcher> _fcache = protected final Map<Key, Mustache.VariableFetcher> _fcache;
new HashMap<Key, Mustache.VariableFetcher>();
protected static class Context protected static class Context
{ {