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=95ab2b331a494cee753ce0cd5b6197873e00a413;hpb=d692bdee6e1d8fd507d38636aa90f7e535dda6d1;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 95ab2b331a..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 @@ -7,7 +7,11 @@ */ package org.opendaylight.mdsal.binding.dom.codec.impl; -import com.google.common.base.Preconditions; +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; @@ -23,36 +27,50 @@ 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 - private final Map getters; + private final ImmutableMap getters; // Ordered by lexical name - private final Set ctorArgs; + private final ImmutableSet ctorArgs; private final MethodHandle ctor; private BitsCodec(final Class typeClass, final MethodHandle ctor, final Set ctorArgs, final Map getters) { super(typeClass); - this.ctor = Preconditions.checkNotNull(ctor); + this.ctor = requireNonNull(ctor); this.ctorArgs = ImmutableSet.copyOf(ctorArgs); 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); @@ -67,13 +85,13 @@ 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 @SuppressWarnings("checkstyle:illegalCatch") public Object deserialize(final Object input) { - Preconditions.checkArgument(input instanceof Set); + checkArgument(input instanceof Set); @SuppressWarnings("unchecked") final Set casted = (Set) input;