diff --git a/common/src/main/java/io/netty/util/Recycler.java b/common/src/main/java/io/netty/util/Recycler.java index 43982dd5f5..51e80d2c01 100644 --- a/common/src/main/java/io/netty/util/Recycler.java +++ b/common/src/main/java/io/netty/util/Recycler.java @@ -269,28 +269,35 @@ public abstract class Recycler { head.next = null; head = next; } - if (reclaimSpace != 0) { + if (reclaimSpace > 0) { reclaimSpace(reclaimSpace); } } - void reclaimSpace(int space) { - assert space >= 0; + private void reclaimSpace(int space) { availableSharedCapacity.addAndGet(space); } - boolean reserveSpace(int space) { - return reserveSpace(availableSharedCapacity, space); + void relink(Link link) { + reclaimSpace(LINK_CAPACITY); + this.link = link; } - static boolean reserveSpace(AtomicInteger availableSharedCapacity, int space) { - assert space >= 0; + /** + * Creates a new {@link} and returns it if we can reserve enough space for it, otherwise it + * returns {@code null}. + */ + Link newLink() { + return reserveSpaceForLink(availableSharedCapacity) ? new Link() : null; + } + + static boolean reserveSpaceForLink(AtomicInteger availableSharedCapacity) { for (;;) { int available = availableSharedCapacity.get(); - if (available < space) { + if (available < LINK_CAPACITY) { return false; } - if (availableSharedCapacity.compareAndSet(available, available - space)) { + if (availableSharedCapacity.compareAndSet(available, available - LINK_CAPACITY)) { return true; } } @@ -324,7 +331,11 @@ public abstract class Recycler { ratioMask = stack.ratioMask; } - private static WeakOrderQueue newQueue(Stack stack, Thread thread) { + static WeakOrderQueue newQueue(Stack stack, Thread thread) { + // We allocated a Link so reserve the space + if (!Head.reserveSpaceForLink(stack.availableSharedCapacity)) { + return null; + } final WeakOrderQueue queue = new WeakOrderQueue(stack, thread); // Done outside of the constructor to ensure WeakOrderQueue.this does not escape the constructor and so // may be accessed while its still constructed. @@ -342,15 +353,6 @@ public abstract class Recycler { this.next = next; } - /** - * Allocate a new {@link WeakOrderQueue} or return {@code null} if not possible. - */ - static WeakOrderQueue allocate(Stack stack, Thread thread) { - // We allocated a Link so reserve the space - return Head.reserveSpace(stack.availableSharedCapacity, LINK_CAPACITY) - ? newQueue(stack, thread) : null; - } - void reclaimAllSpaceAndUnlink() { head.reclaimAllSpaceAndUnlink(); this.next = null; @@ -370,12 +372,13 @@ public abstract class Recycler { Link tail = this.tail; int writeIndex; if ((writeIndex = tail.get()) == LINK_CAPACITY) { - if (!head.reserveSpace(LINK_CAPACITY)) { + Link link = head.newLink(); + if (link == null) { // Drop it. return; } // We allocate a Link so reserve the space - this.tail = tail = tail.next = new Link(); + this.tail = tail = tail.next = link; writeIndex = tail.get(); } @@ -402,8 +405,8 @@ public abstract class Recycler { if (head.next == null) { return false; } - this.head.link = head = head.next; - this.head.reclaimSpace(LINK_CAPACITY); + head = head.next; + this.head.relink(head); } final int srcStart = head.readIndex; @@ -444,8 +447,7 @@ public abstract class Recycler { if (srcEnd == LINK_CAPACITY && head.next != null) { // Add capacity back as the Link is GCed. - this.head.reclaimSpace(LINK_CAPACITY); - this.head.link = head.next; + this.head.relink(head.next); } head.readIndex = srcEnd; @@ -662,7 +664,7 @@ public abstract class Recycler { return; } // Check if we already reached the maximum number of delayed queues and if we can allocate at all. - if ((queue = WeakOrderQueue.allocate(this, thread)) == null) { + if ((queue = newWeakOrderQueue(thread)) == null) { // drop object return; } @@ -675,6 +677,13 @@ public abstract class Recycler { queue.add(item); } + /** + * Allocate a new {@link WeakOrderQueue} or return {@code null} if not possible. + */ + private WeakOrderQueue newWeakOrderQueue(Thread thread) { + return WeakOrderQueue.newQueue(this, thread); + } + boolean dropHandle(DefaultHandle handle) { if (!handle.hasBeenRecycled) { if ((++handleRecycleCount & ratioMask) != 0) {