private void release(final ByteBuffer buffer) {
        if (buffer != null && buffer.isDirect()) {
            // Work out which queue to put the buffer back on
            final int offset = getOffset(buffer.capacity());
            final Queue<ByteBuffer> byteBufferQueue = getByteBufferQueue(offset);
            final Semaphore semaphore = getSemaphore(offset);
            byteBufferQueue.offer(buffer);
            // Now release a permit so any thread waiting on this semaphore can now grab the buffer
            // from the queue
            semaphore.release();
        }
    }
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