All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.hekate.codec.ThreadLocalCodecFactory Maven / Gradle / Ivy

There is a newer version: 4.1.3
Show newest version
/*
 * Copyright 2020 The Hekate Project
 *
 * The Hekate Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package io.hekate.codec;

import io.hekate.core.internal.util.ArgAssert;
import io.hekate.util.format.ToStringIgnore;
import java.io.IOException;

/**
 * Codec factory that manages a per-thread cache of {@link Codec}s.
 *
 * @param  Base data type of this factory.
 */
public final class ThreadLocalCodecFactory implements CodecFactory {
    private final CodecFactory delegate;

    @ToStringIgnore
    // Notice! Non-static because of we need to store a thread-local cache per each factory.
    private final ThreadLocal> cache = new ThreadLocal<>();

    @ToStringIgnore
    private final Codec threadLocalCodec;

    private ThreadLocalCodecFactory(Class baseType, CodecFactory delegate) {
        this.delegate = delegate;

        this.threadLocalCodec = new Codec() {
            @Override
            public boolean isStateful() {
                return false;
            }

            @Override
            public Class baseType() {
                return baseType;
            }

            @Override
            public T decode(DataReader in) throws IOException {
                Codec codec = cache.get();

                if (codec == null) {
                    codec = delegate.createCodec();

                    cache.set(codec);
                }

                return codec.decode(in);
            }

            @Override
            public void encode(T obj, DataWriter out) throws IOException {
                Codec codec = cache.get();

                if (codec == null) {
                    codec = delegate.createCodec();

                    cache.set(codec);
                }

                codec.encode(obj, out);
            }

            @Override
            public String toString() {
                return delegate.toString();
            }
        };
    }

    /**
     * Tries to wrap the specified factory with {@link ThreadLocalCodecFactory}.
     *
     * 

* If the specified factory is {@link Codec#isStateful() stateful} or if it is already an instance of {@link ThreadLocalCodecFactory} * then it will not be wrapped. In such case the value returned by this method will be the same object that was passed in as a * parameter. *

* * @param factory Factory to warp. * @param Factory type. * * @return Wrapped instance or the factory instance that was passed in as a parameter * if such factory is {@link Codec#isStateful() stateful} or if it is already an instance of {@link ThreadLocalCodecFactory}. */ public static CodecFactory tryWrap(CodecFactory factory) { ArgAssert.notNull(factory, "Codec factory is null."); if (factory instanceof ThreadLocalCodecFactory) { return factory; } Codec probe = factory.createCodec(); if (probe.isStateful()) { return factory; } else { return new ThreadLocalCodecFactory<>(probe.baseType(), factory); } } /** * Tries to unwrap the specified factory. * *

* If the specified factory is an instance of {@link ThreadLocalCodecFactory} then a factory that is wrapped by that * {@link ThreadLocalCodecFactory} is returned; otherwise the method's parameter is returned as is. *

* * @param factory Factory to unwrap. * @param Factory data type. * * @return Unwrapped codec factory if the specified parameter is of {@link ThreadLocalCodecFactory} type; otherwise returns the method's * parameter as is. */ @SuppressWarnings("unchecked") public static CodecFactory tryUnwrap(CodecFactory factory) { if (factory instanceof ThreadLocalCodecFactory) { return ((ThreadLocalCodecFactory)factory).delegate; } return factory; } @Override public Codec createCodec() { return threadLocalCodec; } @Override public String toString() { return ThreadLocalCodecFactory.class.getSimpleName() + "[delegate=" + delegate + ']'; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy