X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-codec%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fcodec%2Fimpl%2FBitsCodec.java;h=f5b0908961deabb7e0a6d253e47ad8043053e928;hb=1a2d7e719b78cd564fe37578cab270372628d096;hp=893f2523a445ed133b19093ff4f84f1b7616524e;hpb=4b44410cd93cc764303175c733ebe08d1deefd6a;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java index 893f2523a4..f5b0908961 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java @@ -10,6 +10,8 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static com.google.common.base.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.lang.invoke.MethodHandle; @@ -25,13 +27,26 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.dom.codec.impl.ValueTypeCodec.SchemaUnawareCodec; import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit; final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec { + /* + * Use identity comparison for keys and allow classes to be GCd themselves. + * + * Since codecs can (and typically do) hold a direct or indirect strong reference to the class, they need to be also + * accessed via reference. Using a weak reference could be problematic, because the codec would quite often be only + * weakly reachable. We therefore use a soft reference, whose implementation guidance is suitable to our use case: + * + * "Virtual machine implementations are, however, encouraged to bias against clearing recently-created or + * recently-used soft references." + */ + private static final Cache, @NonNull BitsCodec> CACHE = CacheBuilder.newBuilder().weakKeys().softValues() + .build(); private static final MethodType CONSTRUCTOR_INVOKE_TYPE = MethodType.methodType(Object.class, Boolean[].class); // Ordered by position @@ -48,13 +63,14 @@ final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec this.getters = ImmutableMap.copyOf(getters); } - static Callable loader(final Class returnType, final BitsTypeDefinition rootType) { - return () -> { + static @NonNull BitsCodec of(final Class returnType, final BitsTypeDefinition rootType) + throws ExecutionException { + return CACHE.get(returnType, () -> { final Map getters = new LinkedHashMap<>(); final Set ctorArgs = new TreeSet<>(); for (Bit bit : rootType.getBits()) { - final Method valueGetter = returnType.getMethod(BindingMapping.BOOLEAN_GETTER_PREFIX + final Method valueGetter = returnType.getMethod(BindingMapping.GETTER_PREFIX + BindingMapping.getClassName(bit.getName())); ctorArgs.add(bit.getName()); getters.put(bit.getName(), valueGetter); @@ -69,7 +85,7 @@ final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec final MethodHandle ctor = MethodHandles.publicLookup().unreflectConstructor(constructor) .asSpreader(Boolean[].class, ctorArgs.size()).asType(CONSTRUCTOR_INVOKE_TYPE); return new BitsCodec(returnType, ctor, ctorArgs, getters); - }; + }); } @Override