gt:         if (head == null) {
context: /*
   * Copyright 2012 The Netty Project
   *
   * The Netty Project licenses this file to you under the Apache License,
   * version 2.0 (the "License"); you may not use this file except in compliance
   * with the License. You may obtain a copy of the License at:
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations
   * under the License.
   */
  
  package io.netty_voltpatches.buffer;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Iterator;
  import java.util.List;
  
  import io.netty_voltpatches.util.internal.StringUtil;
  
  import static java.lang.Math.*;
  
  final class PoolChunkList<T> implements PoolChunkListMetric {
      private static final Iterator<PoolChunkMetric> EMPTY_METRICS = Collections.<PoolChunkMetric>emptyList().iterator();
      private final PoolChunkList<T> nextList;
      private final int minUsage;
      private final int maxUsage;
      private final int maxCapacity;
      private PoolChunk<T> head;
  
      // This is only update once when create the linked like list of PoolChunkList in PoolArena constructor.
      private PoolChunkList<T> prevList;
  
      // TODO: Test if adding padding helps under contention
      //private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
  
      PoolChunkList(PoolChunkList<T> nextList, int minUsage, int maxUsage, int chunkSize) {
          assert minUsage <= maxUsage;
          this.nextList = nextList;
          this.minUsage = minUsage;
          this.maxUsage = maxUsage;
          maxCapacity = calculateMaxCapacity(minUsage, chunkSize);
      }
  
      /**
       * Calculates the maximum capacity of a buffer that will ever be possible to allocate out of the {@link PoolChunk}s
       * that belong to the {@link PoolChunkList} with the given {@code minUsage} and {@code maxUsage} settings.
       */
      private static int calculateMaxCapacity(int minUsage, int chunkSize) {
          minUsage = minUsage0(minUsage);
  
          if (minUsage == 100) {
              // If the minUsage is 100 we can not allocate anything out of this list.
              return 0;
          }
  
          // Calculate the maximum amount of bytes that can be allocated from a PoolChunk in this PoolChunkList.
          //
          // As an example:
          // - If a PoolChunkList has minUsage == 25 we are allowed to allocate at most 75% of the chunkSize because
          //   this is the maximum amount available in any PoolChunk in this PoolChunkList.
          return  (int) (chunkSize * (100L - minUsage) / 100L);
      }
  
      void prevList(PoolChunkList<T> prevList) {
          assert this.prevList == null;
          this.prevList = prevList;
      }
  
      boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
          if (head == null || normCapacity > maxCapacity) {
              // Either this PoolChunkList is empty or the requested capacity is larger then the capacity which can
              // be handled by the PoolChunks that are contained in this PoolChunkList.
              return false;
          }
  
          for (PoolChunk<T> cur = head;;) {
              long handle = cur.allocate(normCapacity);
              if (handle < 0) {
                  cur = cur.next;
                  if (cur == null) {
                      return false;
                  }
              } else {
                  cur.initBuf(buf, handle, reqCapacity);
                  if (cur.usage() >= maxUsage) {
                      remove(cur);
                      nextList.add(cur);
                  }
                  return true;
              }
          }
      }
  
      boolean free(PoolChunk<T> chunk, long handle) {
          chunk.free(handle);
          if (chunk.usage() < minUsage) {
              remove(chunk);
              // Move the PoolChunk down the PoolChunkList linked-list.
              return move0(chunk);
          }
          return true;
      }
  
      private boolean move(PoolChunk<T> chunk) {
          assert chunk.usage() < maxUsage;
  
          if (chunk.usage() < minUsage) {
              // Move the PoolChunk down the PoolChunkList linked-list.
              return move0(chunk);
          }
  
          // PoolChunk fits into this PoolChunkList, adding it here.
          add0(chunk);
          return true;
      }
  
      /**
       * Moves the {@link PoolChunk} down the {@link PoolChunkList} linked-list so it will end up in the right
       * {@link PoolChunkList} that has the correct minUsage / maxUsage in respect to {@link PoolChunk#usage()}.
       */
      private boolean move0(PoolChunk<T> chunk) {
          if (prevList == null) {
              // There is no previous PoolChunkList so return false which result in having the PoolChunk destroyed and
              // all memory associated with the PoolChunk will be released.
              assert chunk.usage() == 0;
              return false;
          }
          return prevList.move(chunk);
      }
  
      void add(PoolChunk<T> chunk) {
          if (chunk.usage() >= maxUsage) {
              nextList.add(chunk);
              return;
          }
          add0(chunk);
      }
  
      /**
       * Adds the {@link PoolChunk} to this {@link PoolChunkList}.
       */
      void add0(PoolChunk<T> chunk) {
          chunk.parent = this;
          if (head == null) {
              head = chunk;
              chunk.prev = null;
              chunk.next = null;
          } else {
              chunk.prev = null;
              chunk.next = head;
              head.prev = chunk;
              head = chunk;
          }
      }
  
      private void remove(PoolChunk<T> cur) {
          if (cur == head) {
              head = cur.next;
              if (head != null) {
                  head.prev = null;
              }
          } else {
              PoolChunk<T> next = cur.next;
              cur.prev.next = next;
              if (next != null) {
                  next.prev = cur.prev;
              }
          }
      }
  
      @Override
      public int minUsage() {
          return minUsage0(minUsage);
      }
  
      @Override
      public int maxUsage() {
          return min(maxUsage, 100);
      }
  
      private static int minUsage0(int value) {
          return max(1, value);
      }
  
      @Override
      public Iterator<PoolChunkMetric> iterator() {
          if (head == null) {
              return EMPTY_METRICS;
          }
          List<PoolChunkMetric> metrics = new ArrayList<PoolChunkMetric>();
          for (PoolChunk<T> cur = head;;) {
              metrics.add(cur);
              cur = cur.next;
              if (cur == null) {
                  break;
              }
          }
          return metrics.iterator();
      }
  
      @Override
      public String toString() {
  