de.undercouch.bson4jackson.io.StaticBuffers.java Source code

Java tutorial

Introduction

Here is the source code for de.undercouch.bson4jackson.io.StaticBuffers.java

Source

// Copyright 2010-2011 Michel Kraemer
//
// Licensed 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 de.undercouch.bson4jackson.io;

import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

/**
 * Keeps thread-local re-usable buffers. Each buffer is identified by a key.
 * This class is a singleton, whereas the reference to the instance is hold
 * in a {@link SoftReference} so buffers can be freed when they are not needed
 * anymore.
 * @see com.fasterxml.jackson.core.util.BufferRecycler
 * @author Michel Kraemer
 */
public class StaticBuffers {
    /**
     * All buffers have a minimum size of 64 kb
     */
    public static final int GLOBAL_MIN_SIZE = 1024 * 64;

    /**
     * Possible buffer keys
     */
    public static enum Key {
        BUFFER0, BUFFER1, BUFFER2, BUFFER3, BUFFER4, BUFFER5, BUFFER6, BUFFER7, BUFFER8, BUFFER9
    }

    /**
     * A thread-local soft reference to the singleton instance of this class
     */
    private static final ThreadLocal<SoftReference<StaticBuffers>> _instance = new ThreadLocal<SoftReference<StaticBuffers>>();

    /**
     * Maps of already allocated re-usable buffers
     */
    private ByteBuffer[] _byteBuffers = new ByteBuffer[Key.values().length];
    private CharBuffer[] _charBuffers = new CharBuffer[Key.values().length];

    /**
     * Hidden constructor
     */
    private StaticBuffers() {
        //nothing to do here
    }

    /**
     * @return a thread-local singleton instance of this class
     */
    public static StaticBuffers getInstance() {
        SoftReference<StaticBuffers> ref = _instance.get();
        StaticBuffers buf = (ref == null ? null : ref.get());
        if (buf == null) {
            buf = new StaticBuffers();
            _instance.set(new SoftReference<StaticBuffers>(buf));
        }
        return buf;
    }

    /**
     * Creates or re-uses a {@link CharBuffer} that has a minimum size. Calling
     * this method multiple times with the same key will always return the
     * same buffer, as long as it has the minimum size and is marked to be
     * re-used. Buffers that are allowed to be re-used should be released using
     * {@link #releaseCharBuffer(Key, CharBuffer)}.
     * @param key the buffer's identifier
     * @param minSize the minimum size
     * @return the {@link CharBuffer} instance
     */
    public CharBuffer charBuffer(Key key, int minSize) {
        minSize = Math.max(minSize, GLOBAL_MIN_SIZE);

        CharBuffer r = _charBuffers[key.ordinal()];
        if (r == null || r.capacity() < minSize) {
            r = CharBuffer.allocate(minSize);
        } else {
            _charBuffers[key.ordinal()] = null;
            r.clear();
        }
        return r;
    }

    /**
     * Marks a buffer a being re-usable.
     * @param key the buffer's key
     * @param buf the buffer
     */
    public void releaseCharBuffer(Key key, CharBuffer buf) {
        _charBuffers[key.ordinal()] = buf;
    }

    /**
     * @see #charBuffer(Key, int)
     */
    public ByteBuffer byteBuffer(Key key, int minSize) {
        minSize = Math.max(minSize, GLOBAL_MIN_SIZE);

        ByteBuffer r = _byteBuffers[key.ordinal()];
        if (r == null || r.capacity() < minSize) {
            r = ByteBuffer.allocate(minSize);
        } else {
            _byteBuffers[key.ordinal()] = null;
            r.clear();
        }
        return r;
    }

    /**
     * @see #releaseCharBuffer(Key, CharBuffer)
     */
    public void releaseByteBuffer(Key key, ByteBuffer buf) {
        _byteBuffers[key.ordinal()] = buf;
    }
}