1 package com.fasterxml.jackson.core.util;
2
3 import java.util.concurrent.atomic.AtomicReferenceArray;
4
5 /**
6 * This is a small utility class, whose main functionality is to allow
7 * simple reuse of raw byte/char buffers. It is usually used through
8 * <code>ThreadLocal</code> member of the owning class pointing to
9 * instance of this class through a <code>SoftReference</code>. The
10 * end result is a low-overhead GC-cleanable recycling: hopefully
11 * ideal for use by stream readers.
12 *<p>
13 * Rewritten in 2.10 to be thread-safe (see [jackson-core#479] for details),
14 * to not rely on {@code ThreadLocal} access.
15 */
16 public class BufferRecycler
17 {
18 /**
19 * Buffer used for reading byte-based input.
20 */
21 public final static int BYTE_READ_IO_BUFFER = 0;
22
23 /**
24 * Buffer used for temporarily storing encoded content; used
25 * for example by UTF-8 encoding writer
26 */
27 public final static int BYTE_WRITE_ENCODING_BUFFER = 1;
28
29 /**
30 * Buffer used for temporarily concatenating output; used for
31 * example when requesting output as byte array.
32 */
33 public final static int BYTE_WRITE_CONCAT_BUFFER = 2;
34
35 /**
36 * Buffer used for concatenating binary data that is either being
37 * encoded as base64 output, or decoded from base64 input.
38 *
39 * @since 2.1
40 */
41 public final static int BYTE_BASE64_CODEC_BUFFER = 3;
42
43 /**
44 * Buffer used as input buffer for tokenization for character-based parsers.
45 */
46 public final static int CHAR_TOKEN_BUFFER = 0;
47
48 /**
49 * Buffer used by generators; for byte-backed generators for buffering of
50 * {@link String} values to output (before encoding into UTF-8),
51 * and for char-backed generators as actual concatenation buffer.
52 */
53 public final static int CHAR_CONCAT_BUFFER = 1;
54
55 /**
56 * Used through {@link TextBuffer}: directly by parsers (to concatenate
57 * String values)
58 * and indirectly via
59 * {@link com.fasterxml.jackson.core.io.SegmentedStringWriter}
60 * when serializing (databind level {@code ObjectMapper} and
61 * {@code ObjectWriter}). In both cases used as segments (and not for whole value),
62 * but may result in retention of larger chunks for big content
63 * (long text values during parsing; bigger output documents for generation).
64 */
65 public final static int CHAR_TEXT_BUFFER = 2;
66
67 /**
68 * For parsers, temporary buffer into which {@code char[]} for names is copied
69 * when requested as such; for {@code WriterBasedGenerator} used for buffering
70 * during {@code writeString(Reader)} operation (not commonly used).
71 */
72 public final static int CHAR_NAME_COPY_BUFFER = 3;
73
74 // Buffer lengths
75
76 private final static int[] BYTE_BUFFER_LENGTHS = new int[] { 8000, 8000, 2000, 2000 };
77 private final static int[] CHAR_BUFFER_LENGTHS = new int[] { 4000, 4000, 200, 200 };
78
79 // Note: changed from simple array in 2.10:
80 protected final AtomicReferenceArray<byte[]> _byteBuffers;
81
82 // Note: changed from simple array in 2.10:
83 protected final AtomicReferenceArray<char[]> _charBuffers;
84
85 /*
86 /**********************************************************
87 /* Construction
88 /**********************************************************
89 */
90
91 /**
92 * Default constructor used for creating instances of this default
93 * implementation.
94 */
95 public BufferRecycler() {
96 this(4, 4);
97 }
98
99 /**
100 * Alternate constructor to be used by sub-classes, to allow customization
101 * of number of low-level buffers in use.
102 *
103 * @since 2.4
104 */
105 protected BufferRecycler(int bbCount, int cbCount) {
106 _byteBuffers = new AtomicReferenceArray<byte[]>(bbCount);
107 _charBuffers = new AtomicReferenceArray<char[]>(cbCount);
108 }
109
110 /*
111 /**********************************************************
112 /* Public API, byte buffers
113 /**********************************************************
114 */
115
116 /**
117 * @param ix One of <code>READ_IO_BUFFER</code> constants.
118 */
119 public final byte[] allocByteBuffer(int ix) {
120 return allocByteBuffer(ix, 0);
121 }
122
123 public byte[] allocByteBuffer(int ix, int minSize) {
124 final int DEF_SIZE = byteBufferLength(ix);
125 if (minSize < DEF_SIZE) {
126 minSize = DEF_SIZE;
127 }
128 byte[] buffer = _byteBuffers.getAndSet(ix, null);
129 if (buffer == null || buffer.length < minSize) {
130 buffer = balloc(minSize);
131 }
132 return buffer;
133 }
134
135 public void releaseByteBuffer(int ix, byte[] buffer) {
136 _byteBuffers.set(ix, buffer);
137 }
138
139 /*
140 /**********************************************************
141 /* Public API, char buffers
142 /**********************************************************
143 */
144
145 public final char[] allocCharBuffer(int ix) {
146 return allocCharBuffer(ix, 0);
147 }
148
149 public char[] allocCharBuffer(int ix, int minSize) {
150 final int DEF_SIZE = charBufferLength(ix);
151 if (minSize < DEF_SIZE) {
152 minSize = DEF_SIZE;
153 }
154 char[] buffer = _charBuffers.getAndSet(ix, null);
155 if (buffer == null || buffer.length < minSize) {
156 buffer = calloc(minSize);
157 }
158 return buffer;
159 }
160
161 public void releaseCharBuffer(int ix, char[] buffer) {
162 _charBuffers.set(ix, buffer);
163 }
164
165 /*
166 /**********************************************************
167 /* Overridable helper methods
168 /**********************************************************
169 */
170
171 protected int byteBufferLength(int ix) {
172 return BYTE_BUFFER_LENGTHS[ix];
173 }
174
175 protected int charBufferLength(int ix) {
176 return CHAR_BUFFER_LENGTHS[ix];
177 }
178
179 /*
180 /**********************************************************
181 /* Actual allocations separated for easier debugging/profiling
182 /**********************************************************
183 */
184
185 protected byte[] balloc(int size) { return new byte[size]; }
186 protected char[] calloc(int size) { return new char[size]; }
187 }
188