Repository: netty/netty
File: buffer/src/main/java/io/netty/buffer/AdaptivePoolingAllocator.java (Java)

Code before:
        Magazine magazine = into.chunk.magazine;
        AdaptiveByteBuf result = allocate(size, maxCapacity, Thread.currentThread(), into);
        if (result == null) {
            // Create a one-off chunk for this allocation.
            AbstractByteBuf innerChunk = (AbstractByteBuf) chunkAllocator.allocate(size, maxCapacity);
            ChunkByteBuf chunk = new ChunkByteBuf(innerChunk, magazine, false);
            chunk.readInitInto(into, size, maxCapacity);
        }
    }

    long usedMemory() {
        long sum = 0;
        for (ByteBuf byteBuf : centralQueue) {
            sum += byteBuf.capacity();
        }
        for (Magazine magazine : magazines) {
            sum += magazine.usedMemory.get();
        }
        return sum;
    }

    private boolean tryExpandMagazines(int currentLength) {
        if (currentLength >= MAX_STRIPES) {
            return true;
        }
        long writeLock = magazineExpandLock.tryWriteLock();
        if (writeLock != 0) {
            try {
                Magazine[] mags = magazines;
                if (mags.length >= MAX_STRIPES || mags.length > currentLength) {
                    return true;
                }
                Magazine[] expanded = Arrays.copyOf(mags, mags.length * 2);
                for (int i = mags.length, m = expanded.length; i < m; i++) {
                    expanded[i] = new Magazine(this);
                }
                magazines = expanded;
            } finally {
                magazineExpandLock.unlockWrite(writeLock);
            }
        }
        return true;
    }

    private boolean offerToQueue(ChunkByteBuf buffer) {
        return centralQueue.offer(buffer);
    }

    @SuppressJava6Requirement(reason = "Guarded by version check")
    @SuppressWarnings("checkstyle:finalclass") // Checkstyle mistakenly believes this class should be final.
    private static class AllocationStatistics extends StampedLock {

Review comment (suggestion):
Let's keep this as before and not use `EMPTY_MAGAZINES`.

Code after:
        return PlatformDependent.newFixedMpmcQueue(CENTRAL_QUEUE_CAPACITY);
    }

    ByteBuf allocate(int size, int maxCapacity) {
        if (size <= MAX_CHUNK_SIZE) {
            Thread currentThread = Thread.currentThread();
            boolean willCleanupFastThreadLocals = FastThreadLocalThread.willCleanupFastThreadLocals(currentThread);
            AdaptiveByteBuf buf = AdaptiveByteBuf.newInstance(willCleanupFastThreadLocals);
            AdaptiveByteBuf result = allocate(size, maxCapacity, currentThread, buf);
            if (result != null) {
                return result;
            }
            // Return the buffer we pulled from the recycler but didn't use.
            buf.release();
        }
        // The magazines failed us, or the buffer is too big to be pooled.
        return chunkAllocator.allocate(size, maxCapacity);
    }

    private AdaptiveByteBuf allocate(int size, int maxCapacity, Thread currentThread, AdaptiveByteBuf buf) {
        int sizeBucket = AllocationStatistics.sizeBucket(size); // Compute outside of Magazine lock for better ILP.
        FastThreadLocal<Object> threadLocalMagazine = this.threadLocalMagazine;
        if (threadLocalMagazine != null && currentThread instanceof FastThreadLocalThread) {
            Object mag = threadLocalMagazine.get();
            if (mag != NO_MAGAZINE) {
                return ((Magazine) mag).allocate(size, sizeBucket, maxCapacity, buf);
            }
        }
        long threadId = currentThread.getId();
        Magazine[] mags;
        int expansions = 0;
        do {
            mags = magazines;
            int mask = mags.length - 1;
            int index = (int) (threadId & mask);
            for (int i = 0, m = Integer.numberOfTrailingZeros(~mask); i < m; i++) {
                Magazine mag = mags[index + i & mask];
                long writeLock = mag.tryWriteLock();
                if (writeLock != 0) {
                    try {
                        return mag.allocate(size, sizeBucket, maxCapacity, buf);
                    } finally {
                        mag.unlockWrite(writeLock);
                    }
                }
            }
            expansions++;
        } while (expansions <= EXPANSION_ATTEMPTS && tryExpandMagazines(mags.length));
        return null;
    }