1
14
15 package com.liferay.portal.kernel.util;
16
17 import java.lang.ref.ReferenceQueue;
18 import java.lang.ref.SoftReference;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.concurrent.locks.Lock;
24 import java.util.concurrent.locks.ReentrantLock;
25
26
31 public class CharBufferPool {
32
33 public static char[] borrow(int size) {
34 if (!isEnabled()) {
35 return new char[size];
36 }
37
38 _cleanUpDeadBuffers();
39
40 int poolSize = -1;
41
42 _modifyLock.lock();
43
44 try {
45 int index = Collections.binarySearch(
46 _charBufferHoldersPool, new CharBufferHolder(size));
47
48 if (index < 0) {
49 index = -(index + 1);
50 }
51
52 poolSize = _charBufferHoldersPool.size();
53
54 while (index < poolSize) {
55 CharBufferHolder charBufferHolder = _charBufferHoldersPool.get(
56 index);
57
58 if (charBufferHolder._borrowed) {
59 index++;
60 }
61 else {
62 char[] charBuffer = charBufferHolder.get();
63
64 if (charBuffer != null) {
65 charBufferHolder._borrowed = true;
66
67 List<CharBufferHolder> borrowedCharBufferHolders =
68 _borrowedCharBufferHoldersThreadLocal.get();
69
70 borrowedCharBufferHolders.add(charBufferHolder);
71
72 return charBuffer;
73 }
74
75 _charBufferHoldersPool.remove(index);
76 }
77 }
78 }
79 finally {
80 _modifyLock.unlock();
81 }
82
83 char[] charBuffer = new char[size + (size >> 9)];
84
85 if (poolSize < _MAX_POOL_SIZE) {
86 CharBufferHolder charBufferHolder = new CharBufferHolder(
87 charBuffer);
88
89 List<CharBufferHolder> borrowedCharBufferHolders =
90 _borrowedCharBufferHoldersThreadLocal.get();
91
92 borrowedCharBufferHolders.add(charBufferHolder);
93 }
94
95 return charBuffer;
96 }
97
98 public static void cleanUp() {
99 List<CharBufferHolder> charBufferHolders =
100 _borrowedCharBufferHoldersThreadLocal.get();
101
102 _modifyLock.lock();
103
104 try {
105 for (CharBufferHolder charBufferHolder :
106 charBufferHolders) {
107
108 if (charBufferHolder._borrowed) {
109 charBufferHolder._borrowed = false;
110 }
111 else {
112 int index = Collections.binarySearch(
113 _charBufferHoldersPool, charBufferHolder);
114
115 if (index < 0) {
116 index = -(index + 1);
117 }
118
119 _charBufferHoldersPool.add(index, charBufferHolder);
120 }
121 }
122 }
123 finally {
124 _modifyLock.unlock();
125 }
126
127 charBufferHolders.clear();
128
129 _cleanUpDeadBuffers();
130 }
131
132 public static boolean isEnabled() {
133 return _enabledThreadLocal.get();
134 }
135
136 public static void setEnabled(boolean enabled) {
137 _enabledThreadLocal.set(enabled);
138 }
139
140 private static void _cleanUpDeadBuffers() {
141
142
150 CharBufferHolder charBufferHolder =
151 (CharBufferHolder)_referenceQueue.poll();
152
153 if (charBufferHolder == null) {
154 return;
155 }
156
157 _modifyLock.lock();
158
159 try {
160 do {
161 _charBufferHoldersPool.remove(charBufferHolder);
162 }
163 while ((charBufferHolder =
164 (CharBufferHolder)_referenceQueue.poll()) != null);
165 }
166 finally {
167 _modifyLock.unlock();
168 }
169 }
170
171
177 private static final int _INITIAL_POOL_SIZE = 50;
178
179
184 private static final int _MAX_POOL_SIZE = _INITIAL_POOL_SIZE * 2;
185
186 private static ThreadLocal<List<CharBufferHolder>>
187 _borrowedCharBufferHoldersThreadLocal =
188 new AutoResetThreadLocal<List<CharBufferHolder>>(
189 new ArrayList<CharBufferHolder>());
190 private static List<CharBufferHolder> _charBufferHoldersPool =
191 new ArrayList<CharBufferHolder>(_INITIAL_POOL_SIZE);
192 private static ThreadLocal<Boolean> _enabledThreadLocal =
193 new AutoResetThreadLocal<Boolean>(false);
194 private static Lock _modifyLock = new ReentrantLock();
195 private static ReferenceQueue<Object> _referenceQueue =
196 new ReferenceQueue<Object>();
197
198 private static class CharBufferHolder
199 extends SoftReference<char[]> implements Comparable<CharBufferHolder> {
200
201 public CharBufferHolder(char[] charBuffer) {
202 super(charBuffer, _referenceQueue);
203
204 _length = charBuffer.length;
205 }
206
207 public CharBufferHolder(int length) {
208 super(null);
209
210 _length = length;
211 }
212
213 public int compareTo(CharBufferHolder charBufferHolder) {
214 return _length - charBufferHolder._length;
215 }
216
217 private boolean _borrowed;
218 private int _length;
219
220 }
221
222 }