Skip to content

Commit

Permalink
Thread safe method cache
Browse files Browse the repository at this point in the history
  • Loading branch information
cconroy committed Oct 28, 2015
1 parent fe101c1 commit 7abeb16
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java
Expand Up @@ -20,6 +20,7 @@


import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import com.google.common.base.Converter; import com.google.common.base.Converter;
import com.google.common.collect.MapMaker;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
Expand All @@ -44,10 +45,10 @@
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentMap;


/** /**
* GSON type adapter for protocol buffers that knows how to serialize enums either by using their * GSON type adapter for protocol buffers that knows how to serialize enums either by using their
Expand Down Expand Up @@ -190,6 +191,9 @@ public static Builder newBuilder() {
private static final com.google.protobuf.Descriptors.FieldDescriptor.Type ENUM_TYPE = private static final com.google.protobuf.Descriptors.FieldDescriptor.Type ENUM_TYPE =
com.google.protobuf.Descriptors.FieldDescriptor.Type.ENUM; com.google.protobuf.Descriptors.FieldDescriptor.Type.ENUM;


private static final ConcurrentMap<String, Map<Class<?>, Method>> mapOfMapOfMethods =
new MapMaker().makeMap();

private final EnumSerialization enumSerialization; private final EnumSerialization enumSerialization;
private final Converter<String, String> fieldNameSerializationFormat; private final Converter<String, String> fieldNameSerializationFormat;
private final Set<Extension<FieldOptions, String>> serializedNameExtensions; private final Set<Extension<FieldOptions, String>> serializedNameExtensions;
Expand Down Expand Up @@ -380,18 +384,23 @@ private EnumValueDescriptor findValueByNameAndExtension(EnumDescriptor desc,
} }
} }


private static Method getCachedMethod(Class<?> clazz, String methodName) private static Method getCachedMethod(Class<?> clazz, String methodName,
throws NoSuchMethodException { Class<?>... methodParamTypes) throws NoSuchMethodException {
if (!mapOfMapOfMethods.containsKey(methodName)) {
mapOfMapOfMethods.put(methodName, new HashMap<Class<?>, Method>());
}
Map<Class<?>, Method> mapOfMethods = mapOfMapOfMethods.get(methodName); Map<Class<?>, Method> mapOfMethods = mapOfMapOfMethods.get(methodName);
if (!mapOfMethods.containsKey(clazz)) { if (mapOfMethods == null) {
mapOfMethods.put(clazz, clazz.getMethod(methodName)); mapOfMethods = new MapMaker().makeMap();
Map<Class<?>, Method> previous =
mapOfMapOfMethods.putIfAbsent(methodName, mapOfMethods);
mapOfMethods = previous == null ? mapOfMethods : previous;
}

Method method = mapOfMethods.get(clazz);
if (method == null) {
method = clazz.getMethod(methodName, methodParamTypes);
mapOfMethods.putIfAbsent(clazz, method);
// NB: it doesn't matter which method we return in the event of a race.
} }
return mapOfMethods.get(clazz); return method;
} }


private static Map<String, Map<Class<?>, Method>> mapOfMapOfMethods =
new HashMap<String, Map<Class<?>, Method>>();
} }

0 comments on commit 7abeb16

Please sign in to comment.