Skip to content

Commit 1de2ad5

Browse files
authored
Merge pull request #750 from theigl/746-pool-max-capacity
#746 Ensure pool maximum capacity is honored
2 parents 793b6aa + 2559676 commit 1de2ad5

File tree

3 files changed

+60
-31
lines changed

3 files changed

+60
-31
lines changed

eclipse/code-format.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
164164
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
165165
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
166-
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
166+
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
167167
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
168168
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
169169
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>

src/com/esotericsoftware/kryo/util/Pool.java

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,27 +45,34 @@ public Pool (boolean threadSafe, boolean softReferences) {
4545
public Pool (boolean threadSafe, boolean softReferences, final int maximumCapacity) {
4646
Queue<T> queue;
4747
if (threadSafe)
48-
queue = new LinkedBlockingQueue(maximumCapacity);
48+
queue = new LinkedBlockingQueue<T>(maximumCapacity) {
49+
@Override
50+
public boolean add (T o) {
51+
if (size() >= maximumCapacity) return false;
52+
super.add(o);
53+
return true;
54+
}
55+
};
4956
else if (softReferences) {
50-
queue = new LinkedList() { // More efficient clean() than ArrayDeque.
57+
queue = new LinkedList<T>() { // More efficient clean() than ArrayDeque.
5158
@Override
52-
public boolean add (Object object) {
59+
public boolean add (T object) {
5360
if (size() >= maximumCapacity) return false;
5461
super.add(object);
5562
return true;
5663
}
5764
};
5865
} else {
59-
queue = new ArrayDeque() {
66+
queue = new ArrayDeque<T>() {
6067
@Override
61-
public boolean add (Object object) {
68+
public boolean offer (T object) {
6269
if (size() >= maximumCapacity) return false;
63-
super.add(object);
70+
super.offer(object);
6471
return true;
6572
}
6673
};
6774
}
68-
freeObjects = softReferences ? new SoftReferenceQueue(queue) : queue;
75+
freeObjects = softReferences ? new SoftReferenceQueue<>(((Queue<SoftReference<T>>)queue)) : queue;
6976
}
7077

7178
protected abstract T create ();
@@ -86,7 +93,7 @@ public void free (T object) {
8693
if (object == null) throw new IllegalArgumentException("object cannot be null.");
8794
reset(object);
8895
if (!freeObjects.offer(object) && freeObjects instanceof SoftReferenceQueue) {
89-
((SoftReferenceQueue)freeObjects).cleanOne();
96+
((SoftReferenceQueue<T>)freeObjects).cleanOne();
9097
freeObjects.offer(object);
9198
}
9299
peak = Math.max(peak, freeObjects.size());
@@ -108,7 +115,7 @@ public void clear () {
108115
* capacity. It is not necessary to call {@link #clean()} before calling {@link #free(Object)}, which will try to remove an
109116
* empty reference if the maximum capacity has been reached. */
110117
public void clean () {
111-
if (freeObjects instanceof SoftReferenceQueue) ((SoftReferenceQueue)freeObjects).clean();
118+
if (freeObjects instanceof SoftReferenceQueue) ((SoftReferenceQueue<T>)freeObjects).clean();
112119
}
113120

114121
/** The number of objects available to be obtained.
@@ -140,16 +147,16 @@ public static interface Poolable {
140147
/** Wraps queue values with {@link SoftReference} for {@link Pool}.
141148
* @author Martin Grotzke */
142149
static class SoftReferenceQueue<T> implements Queue<T> {
143-
private Queue delegate;
150+
private final Queue<SoftReference<T>> delegate;
144151

145-
public SoftReferenceQueue (Queue delegate) {
152+
public SoftReferenceQueue (Queue<SoftReference<T>> delegate) {
146153
this.delegate = delegate;
147154
}
148155

149156
@Override
150157
public T poll () {
151158
while (true) {
152-
SoftReference<T> reference = (SoftReference<T>)delegate.poll();
159+
SoftReference<T> reference = delegate.poll();
153160
if (reference == null) return null;
154161
T object = reference.get();
155162
if (object != null) return object;
@@ -158,7 +165,7 @@ public T poll () {
158165

159166
@Override
160167
public boolean offer (T e) {
161-
return delegate.add(new SoftReference(e));
168+
return delegate.add(new SoftReference<>(e));
162169
}
163170

164171
@Override
@@ -172,17 +179,16 @@ public void clear () {
172179
}
173180

174181
void cleanOne () {
175-
for (Iterator iter = delegate.iterator(); iter.hasNext();) {
176-
if (((SoftReference)iter.next()).get() == null) {
182+
for (Iterator<SoftReference<T>> iter = delegate.iterator(); iter.hasNext();) {
183+
if (iter.next().get() == null) {
177184
iter.remove();
178185
break;
179186
}
180187
}
181188
}
182189

183190
void clean () {
184-
for (Iterator iter = delegate.iterator(); iter.hasNext();)
185-
if (((SoftReference)iter.next()).get() == null) iter.remove();
191+
delegate.removeIf(o -> o.get() == null);
186192
}
187193

188194
@Override

test/com/esotericsoftware/kryo/util/PoolTest.java

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
import java.util.Arrays;
2828
import java.util.Collection;
29+
import java.util.List;
30+
import java.util.stream.Collectors;
31+
import java.util.stream.IntStream;
2932

3033
import org.junit.Before;
3134
import org.junit.Test;
@@ -35,19 +38,16 @@
3538

3639
@RunWith(Parameterized.class)
3740
public class PoolTest extends KryoTestCase {
41+
42+
private static final int MAXIMUM_CAPACITY = 4;
43+
3844
@Parameters
3945
public static Collection<Object[]> data () {
40-
return Arrays.asList(new Object[][] {{new Pool<Kryo>(true, false, 16) {
41-
@Override
42-
protected Kryo create () {
43-
return new Kryo();
44-
}
45-
}}, {new Pool<Kryo>(true, true, 16) {
46-
@Override
47-
protected Kryo create () {
48-
return new Kryo();
49-
}
50-
}}});
46+
return Arrays.asList(new Object[][] {
47+
{new TestPool(false, false, MAXIMUM_CAPACITY)},
48+
{new TestPool(true, false, MAXIMUM_CAPACITY)},
49+
{new TestPool(false, true, MAXIMUM_CAPACITY)},
50+
{new TestPool(true, true, MAXIMUM_CAPACITY)}});
5151
}
5252

5353
private final Pool<Kryo> pool;
@@ -63,20 +63,31 @@ public void beforeMethod () {
6363
}
6464

6565
@Test
66-
public void getShouldReturnAvailableInstance () {
66+
public void obtainShouldReturnAvailableInstance () {
6767
Kryo kryo = pool.obtain();
6868
pool.free(kryo);
6969
assertSame(kryo, pool.obtain());
7070
}
7171

7272
@Test
73-
public void releaseShouldAddKryoToPool () {
73+
public void freeShouldAddKryoToPool () {
7474
assertEquals(0, pool.getFree());
7575
Kryo kryo = pool.obtain();
7676
pool.free(kryo);
7777
assertEquals(1, pool.getFree());
7878
}
7979

80+
@Test
81+
public void freeShouldNotAddMoreThanMaximumCapacityToKryoPool () {
82+
final List<Kryo> kryos = IntStream.rangeClosed(0, MAXIMUM_CAPACITY + 1)
83+
.mapToObj(i -> pool.obtain())
84+
.collect(Collectors.toList());
85+
for (Kryo kryo : kryos) {
86+
pool.free(kryo);
87+
}
88+
assertEquals(MAXIMUM_CAPACITY, pool.getFree());
89+
}
90+
8091
@Test
8192
public void testSize () {
8293
assertEquals(0, pool.getFree());
@@ -89,4 +100,16 @@ public void testSize () {
89100
pool.free(kryo2);
90101
assertEquals(2, pool.getFree());
91102
}
103+
104+
private static class TestPool extends Pool<Kryo> {
105+
106+
public TestPool (boolean threadSafe, boolean softReferences, int maximumCapacity) {
107+
super(threadSafe, softReferences, maximumCapacity);
108+
}
109+
110+
@Override
111+
protected Kryo create () {
112+
return new Kryo();
113+
}
114+
}
92115
}

0 commit comments

Comments
 (0)