package com.fasterxml.jackson.core.util;
import java.util.concurrent.atomic.AtomicReferenceArray;
This is a small utility class, whose main functionality is to allow
simple reuse of raw byte/char buffers. It is usually used through
ThreadLocal
member of the owning class pointing to
instance of this class through a SoftReference
. The
end result is a low-overhead GC-cleanable recycling: hopefully
ideal for use by stream readers.
Rewritten in 2.10 to be thread-safe (see [jackson-core#479] for details), to not rely on ThreadLocal
access.
/**
* This is a small utility class, whose main functionality is to allow
* simple reuse of raw byte/char buffers. It is usually used through
* <code>ThreadLocal</code> member of the owning class pointing to
* instance of this class through a <code>SoftReference</code>. The
* end result is a low-overhead GC-cleanable recycling: hopefully
* ideal for use by stream readers.
*<p>
* Rewritten in 2.10 to be thread-safe (see [jackson-core#479] for details),
* to not rely on {@code ThreadLocal} access.
*/
public class BufferRecycler
{
Buffer used for reading byte-based input.
/**
* Buffer used for reading byte-based input.
*/
public final static int BYTE_READ_IO_BUFFER = 0;
Buffer used for temporarily storing encoded content; used
for example by UTF-8 encoding writer
/**
* Buffer used for temporarily storing encoded content; used
* for example by UTF-8 encoding writer
*/
public final static int BYTE_WRITE_ENCODING_BUFFER = 1;
Buffer used for temporarily concatenating output; used for
example when requesting output as byte array.
/**
* Buffer used for temporarily concatenating output; used for
* example when requesting output as byte array.
*/
public final static int BYTE_WRITE_CONCAT_BUFFER = 2;
Buffer used for concatenating binary data that is either being
encoded as base64 output, or decoded from base64 input.
Since: 2.1
/**
* Buffer used for concatenating binary data that is either being
* encoded as base64 output, or decoded from base64 input.
*
* @since 2.1
*/
public final static int BYTE_BASE64_CODEC_BUFFER = 3;
Buffer used as input buffer for tokenization for character-based parsers.
/**
* Buffer used as input buffer for tokenization for character-based parsers.
*/
public final static int CHAR_TOKEN_BUFFER = 0;
Buffer used by generators; for byte-backed generators for buffering of String
values to output (before encoding into UTF-8), and for char-backed generators as actual concatenation buffer. /**
* Buffer used by generators; for byte-backed generators for buffering of
* {@link String} values to output (before encoding into UTF-8),
* and for char-backed generators as actual concatenation buffer.
*/
public final static int CHAR_CONCAT_BUFFER = 1;
Used through TextBuffer
: directly by parsers (to concatenate String values) and indirectly via SegmentedStringWriter
when serializing (databind level ObjectMapper
and ObjectWriter
). In both cases used as segments (and not for whole value), but may result in retention of larger chunks for big content (long text values during parsing; bigger output documents for generation). /**
* Used through {@link TextBuffer}: directly by parsers (to concatenate
* String values)
* and indirectly via
* {@link com.fasterxml.jackson.core.io.SegmentedStringWriter}
* when serializing (databind level {@code ObjectMapper} and
* {@code ObjectWriter}). In both cases used as segments (and not for whole value),
* but may result in retention of larger chunks for big content
* (long text values during parsing; bigger output documents for generation).
*/
public final static int CHAR_TEXT_BUFFER = 2;
For parsers, temporary buffer into which char[]
for names is copied when requested as such; for WriterBasedGenerator
used for buffering during writeString(Reader)
operation (not commonly used). /**
* For parsers, temporary buffer into which {@code char[]} for names is copied
* when requested as such; for {@code WriterBasedGenerator} used for buffering
* during {@code writeString(Reader)} operation (not commonly used).
*/
public final static int CHAR_NAME_COPY_BUFFER = 3;
// Buffer lengths
private final static int[] BYTE_BUFFER_LENGTHS = new int[] { 8000, 8000, 2000, 2000 };
private final static int[] CHAR_BUFFER_LENGTHS = new int[] { 4000, 4000, 200, 200 };
// Note: changed from simple array in 2.10:
protected final AtomicReferenceArray<byte[]> _byteBuffers;
// Note: changed from simple array in 2.10:
protected final AtomicReferenceArray<char[]> _charBuffers;
/*
/**********************************************************
/* Construction
/**********************************************************
*/
Default constructor used for creating instances of this default
implementation.
/**
* Default constructor used for creating instances of this default
* implementation.
*/
public BufferRecycler() {
this(4, 4);
}
Alternate constructor to be used by sub-classes, to allow customization
of number of low-level buffers in use.
Params: - bbCount – Number of
byte[]
buffers to allocate - cbCount – Number of
char[]
buffers to allocate
Since: 2.4
/**
* Alternate constructor to be used by sub-classes, to allow customization
* of number of low-level buffers in use.
*
* @param bbCount Number of {@code byte[]} buffers to allocate
* @param cbCount Number of {@code char[]} buffers to allocate
*
* @since 2.4
*/
protected BufferRecycler(int bbCount, int cbCount) {
_byteBuffers = new AtomicReferenceArray<byte[]>(bbCount);
_charBuffers = new AtomicReferenceArray<char[]>(cbCount);
}
/*
/**********************************************************
/* Public API, byte buffers
/**********************************************************
*/
Params: - ix – One of
READ_IO_BUFFER
constants.
Returns: Buffer allocated (possibly recycled)
/**
* @param ix One of <code>READ_IO_BUFFER</code> constants.
*
* @return Buffer allocated (possibly recycled)
*/
public final byte[] allocByteBuffer(int ix) {
return allocByteBuffer(ix, 0);
}
public byte[] allocByteBuffer(int ix, int minSize) {
final int DEF_SIZE = byteBufferLength(ix);
if (minSize < DEF_SIZE) {
minSize = DEF_SIZE;
}
byte[] buffer = _byteBuffers.getAndSet(ix, null);
if (buffer == null || buffer.length < minSize) {
buffer = balloc(minSize);
}
return buffer;
}
public void releaseByteBuffer(int ix, byte[] buffer) {
_byteBuffers.set(ix, buffer);
}
/*
/**********************************************************
/* Public API, char buffers
/**********************************************************
*/
public final char[] allocCharBuffer(int ix) {
return allocCharBuffer(ix, 0);
}
public char[] allocCharBuffer(int ix, int minSize) {
final int DEF_SIZE = charBufferLength(ix);
if (minSize < DEF_SIZE) {
minSize = DEF_SIZE;
}
char[] buffer = _charBuffers.getAndSet(ix, null);
if (buffer == null || buffer.length < minSize) {
buffer = calloc(minSize);
}
return buffer;
}
public void releaseCharBuffer(int ix, char[] buffer) {
_charBuffers.set(ix, buffer);
}
/*
/**********************************************************
/* Overridable helper methods
/**********************************************************
*/
protected int byteBufferLength(int ix) {
return BYTE_BUFFER_LENGTHS[ix];
}
protected int charBufferLength(int ix) {
return CHAR_BUFFER_LENGTHS[ix];
}
/*
/**********************************************************
/* Actual allocations separated for easier debugging/profiling
/**********************************************************
*/
protected byte[] balloc(int size) { return new byte[size]; }
protected char[] calloc(int size) { return new char[size]; }
}