Skip to content

Commit 94d7557

Browse files
committed
Ensure WeakOrderQueue can be collected fast enough
Motivation: Commit afafadd introduced a change which stored the Stack in the WeakOrderQueue as field. This unfortunally had the effect that it was not removed from the WeakHashMap anymore as the Stack also is used as key. Modifications: Do not store a reference to the Stack in WeakOrderQueue. Result: WeakOrderQueue can be collected correctly again.
1 parent 3ebbd96 commit 94d7557

1 file changed

Lines changed: 29 additions & 24 deletions

File tree

common/src/main/java/io/netty/util/Recycler.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ private static final class Link extends AtomicInteger {
223223
private WeakOrderQueue next;
224224
private final WeakReference<Thread> owner;
225225
private final int id = ID_GENERATOR.getAndIncrement();
226-
private final Stack<?> stack;
226+
private final AtomicInteger availableSharedCapacity;
227227

228228
WeakOrderQueue(Stack<?> stack, Thread thread) {
229229
head = tail = new Link();
@@ -232,19 +232,42 @@ private static final class Link extends AtomicInteger {
232232
next = stack.head;
233233
stack.head = this;
234234
}
235-
this.stack = stack;
235+
236+
// Its important that we not store the Stack itself in the WeakOrderQueue as the Stack also is used in
237+
// the WeakHashMap as key. So just store the enclosed AtomicInteger which should allow to have the
238+
// Stack itself GCed.
239+
availableSharedCapacity = stack.availableSharedCapacity;
240+
236241
// We allocated a Link so reserve the space
237-
boolean reserved = stack.reserveSpace(LINK_CAPACITY);
242+
boolean reserved = reserveSpace(LINK_CAPACITY);
238243
assert reserved;
239244
}
240245

246+
private boolean reserveSpace(int space) {
247+
assert space >= 0;
248+
for (;;) {
249+
int available = availableSharedCapacity.get();
250+
if (available < space) {
251+
return false;
252+
}
253+
if (availableSharedCapacity.compareAndSet(available, available - space)) {
254+
return true;
255+
}
256+
}
257+
}
258+
259+
private void reclaimSpace(int space) {
260+
assert space >= 0;
261+
availableSharedCapacity.addAndGet(space);
262+
}
263+
241264
void add(DefaultHandle<?> handle) {
242265
handle.lastRecycledId = id;
243266

244267
Link tail = this.tail;
245268
int writeIndex;
246269
if ((writeIndex = tail.get()) == LINK_CAPACITY) {
247-
if (!stack.reserveSpace(LINK_CAPACITY)) {
270+
if (!reserveSpace(LINK_CAPACITY)) {
248271
// Drop it.
249272
return;
250273
}
@@ -314,7 +337,7 @@ boolean transfer(Stack<?> dst) {
314337

315338
if (srcEnd == LINK_CAPACITY && head.next != null) {
316339
// Add capacity back as the Link is GCed.
317-
stack.reclaimSpace(LINK_CAPACITY);
340+
reclaimSpace(LINK_CAPACITY);
318341

319342
this.head = head.next;
320343
}
@@ -339,7 +362,7 @@ static final class Stack<T> {
339362
private DefaultHandle<?>[] elements;
340363
private final int maxCapacity;
341364
private int size;
342-
private final AtomicInteger availableSharedCapacity;
365+
final AtomicInteger availableSharedCapacity;
343366

344367
private volatile WeakOrderQueue head;
345368
private WeakOrderQueue cursor, prev;
@@ -352,24 +375,6 @@ static final class Stack<T> {
352375
elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)];
353376
}
354377

355-
boolean reserveSpace(int space) {
356-
assert space >= 0;
357-
for (;;) {
358-
int available = availableSharedCapacity.get();
359-
if (available < space) {
360-
return false;
361-
}
362-
if (availableSharedCapacity.compareAndSet(available, available - space)) {
363-
return true;
364-
}
365-
}
366-
}
367-
368-
void reclaimSpace(int space) {
369-
assert space >= 0;
370-
availableSharedCapacity.addAndGet(space);
371-
}
372-
373378
int increaseCapacity(int expectedCapacity) {
374379
int newCapacity = elements.length;
375380
int maxCapacity = this.maxCapacity;

0 commit comments

Comments
 (0)