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

Code before:
        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;
                }
                int preferredChunkSize = mags[0].sharedPrefChunkSize;
                Magazine[] expanded = new Magazine[mags.length * 2];
                for (int i = 0, m = expanded.length; i < m; i++) {
                    expanded[i] = new Magazine(this);
                    expanded[i].localPrefChunkSize = preferredChunkSize;
                    expanded[i].sharedPrefChunkSize = preferredChunkSize;
                }
                magazines = expanded;
                for (Magazine magazine : mags) {
                    long stamp = magazine.allocationLock.writeLock();
                    try {
                        magazine.free();
                    } finally {
                        magazine.allocationLock.unlockWrite(stamp);
                    }
                }
            } finally {
                magazineExpandLock.unlockWrite(writeLock);
            }
        }
        return true;
    }

    private boolean offerToQueue(Chunk buffer) {
        if (freed) {
            return false;
        }
        return centralQueue.offer(buffer);
    }

    // Ensure that we release all previous pooled resources when this object is finalized. This is needed as otherwise
    // we might end up with leaks. While these leaks are usually harmless in reality it would still at least be
    // very confusing for users.
    @Override
    protected void finalize() throws Throwable {
        try {
            super.finalize();

Review comment (suggestion):
I would move the locking to the `free()` method. That is also consistent with what we do in `tryAllocate(...)`

Code after:
        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;
                }
                int preferredChunkSize = mags[0].sharedPrefChunkSize;
                Magazine[] expanded = new Magazine[mags.length * 2];
                for (int i = 0, l = expanded.length; i < l; i++) {
                    Magazine m = new Magazine(this);
                    m.localPrefChunkSize = preferredChunkSize;
                    m.sharedPrefChunkSize = preferredChunkSize;
                    expanded[i] = m;
                }
                magazines = expanded;
                for (Magazine magazine : mags) {
                    magazine.free();
                }
            } finally {
                magazineExpandLock.unlockWrite(writeLock);
            }
        }
        return true;
    }

    private boolean offerToQueue(Chunk buffer) {
        if (freed) {
            return false;
        }
        return centralQueue.offer(buffer);
    }

    // Ensure that we release all previous pooled resources when this object is finalized. This is needed as otherwise
    // we might end up with leaks. While these leaks are usually harmless in reality it would still at least be
    // very confusing for users.
    @Override
    protected void finalize() throws Throwable {
        try {
            super.finalize();
        } finally {
            free();
        }
    }