private ByteBuffer createNewBufferIfAllowed(final int offset) {
        final int roundedCapacity = SIZES[offset];
        final int maxBufferCount = MAX_BUFFER_COUNTS[offset];
        final AtomicInteger bufferCounter = pooledBufferCounts.get(offset);
        ByteBuffer byteBuffer = null;

        while (true) {
            int currBufferCount = bufferCounter.get();
            if (currBufferCount < maxBufferCount) {
                if (bufferCounter.compareAndSet(currBufferCount, currBufferCount + 1)) {
                    // Succeeded in incrementing the count so we can create one
                    byteBuffer = ByteBuffer.allocateDirect(roundedCapacity);
                    break;
                } else {
                    // CAS failed so another thread beat us, go round again.
                }
            } else {
                // At max count so can't create any more
                break;
            }
        }
        return byteBuffer;
    }
An bounded self-populating pool of directly allocated ByteBuffers.
The pool holds buffers in a fixed set of sizes and any request for a buffer
will result in a buffer with capacity >= the requested capacity being
returned.
All buffers are cleared ready for use when obtained from the pool.
Once a buffer has been returned to the pool it MUST not be used else
bad things will happen.
<p>
This impl uses lock free {@link ConcurrentLinkedQueue} and {@link Semaphore}
stroom-bytebuffer/src/main/java/stroom/bytebuffer/ByteBufferPoolImpl5.java