BufferAllocator.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.arrow.memory;
import java.util.Collection;
import org.apache.arrow.memory.rounding.DefaultRoundingPolicy;
import org.apache.arrow.memory.rounding.RoundingPolicy;
import org.checkerframework.checker.nullness.qual.Nullable;
/** Wrapper class to deal with byte buffer allocation. Ensures users only use designated methods. */
public interface BufferAllocator extends AutoCloseable {
/**
* Allocate a new or reused buffer of the provided size. Note that the buffer may technically be
* larger than the requested size for rounding purposes. However, the buffer's capacity will be
* set to the configured size.
*
* @param size The size in bytes.
* @return a new ArrowBuf, or null if the request can't be satisfied
* @throws OutOfMemoryException if buffer cannot be allocated
*/
ArrowBuf buffer(long size);
/**
* Allocate a new or reused buffer of the provided size. Note that the buffer may technically be
* larger than the requested size for rounding purposes. However, the buffer's capacity will be
* set to the configured size.
*
* @param size The size in bytes.
* @param manager A buffer manager to manage reallocation.
* @return a new ArrowBuf, or null if the request can't be satisfied
* @throws OutOfMemoryException if buffer cannot be allocated
*/
ArrowBuf buffer(long size, BufferManager manager);
/**
* Get the root allocator of this allocator. If this allocator is already a root, return this
* directly.
*
* @return The root allocator
*/
BufferAllocator getRoot();
/**
* Create a new child allocator.
*
* @param name the name of the allocator.
* @param initReservation the initial space reservation (obtained from this allocator)
* @param maxAllocation maximum amount of space the new allocator can allocate
* @return the new allocator, or null if it can't be created
*/
BufferAllocator newChildAllocator(String name, long initReservation, long maxAllocation);
/**
* Create a new child allocator.
*
* @param name the name of the allocator.
* @param listener allocation listener for the newly created child
* @param initReservation the initial space reservation (obtained from this allocator)
* @param maxAllocation maximum amount of space the new allocator can allocate
* @return the new allocator, or null if it can't be created
*/
BufferAllocator newChildAllocator(
String name, AllocationListener listener, long initReservation, long maxAllocation);
/**
* Close and release all buffers generated from this buffer pool.
*
* <p>When assertions are on, complains if there are any outstanding buffers; to avoid that,
* release all buffers before the allocator is closed.
*/
@Override
void close();
/**
* Returns the amount of memory currently allocated from this allocator.
*
* @return the amount of memory currently allocated
*/
long getAllocatedMemory();
/**
* Return the current maximum limit this allocator imposes.
*
* @return Limit in number of bytes.
*/
long getLimit();
/**
* Return the initial reservation.
*
* @return reservation in bytes.
*/
long getInitReservation();
/**
* Set the maximum amount of memory this allocator is allowed to allocate.
*
* @param newLimit The new Limit to apply to allocations
*/
void setLimit(long newLimit);
/**
* Returns the peak amount of memory allocated from this allocator.
*
* @return the peak amount of memory allocated
*/
long getPeakMemoryAllocation();
/**
* Returns the amount of memory that can probably be allocated at this moment without exceeding
* this or any parents allocation maximum.
*
* @return Headroom in bytes
*/
long getHeadroom();
/**
* Forcibly allocate bytes. Returns whether the allocation fit within limits.
*
* @param size to increase
* @return Whether the allocation fit within limits.
*/
boolean forceAllocate(long size);
/**
* Release bytes from this allocator.
*
* @param size to release
*/
void releaseBytes(long size);
/**
* Returns the allocation listener used by this allocator.
*
* @return the {@link AllocationListener} instance. Or {@link AllocationListener#NOOP} by default
* if no listener is configured when this allocator was created.
*/
AllocationListener getListener();
/**
* Returns the parent allocator.
*
* @return parent allocator
*/
@Nullable
BufferAllocator getParentAllocator();
/**
* Returns the set of child allocators.
*
* @return set of child allocators
*/
Collection<BufferAllocator> getChildAllocators();
/**
* Create an allocation reservation. A reservation is a way of building up a request for a buffer
* whose size is not known in advance. See
*
* @return the newly created reservation
* @see AllocationReservation
*/
AllocationReservation newReservation();
/**
* Get a reference to the empty buffer associated with this allocator. Empty buffers are special
* because we don't worry about them leaking or managing reference counts on them since they don't
* actually point to any memory.
*
* @return the empty buffer
*/
ArrowBuf getEmpty();
/**
* Return the name of this allocator. This is a human readable name that can help debugging.
* Typically provides coordinates about where this allocator was created
*
* @return the name of the allocator
*/
String getName();
/**
* Return whether or not this allocator (or one if its parents) is over its limits. In the case
* that an allocator is over its limit, all consumers of that allocator should aggressively try to
* address the overlimit situation.
*
* @return whether or not this allocator (or one if its parents) is over its limits
*/
boolean isOverLimit();
/**
* Return a verbose string describing this allocator. If in DEBUG mode, this will also include
* relevant stacktraces and historical logs for underlying objects
*
* @return A very verbose description of the allocator hierarchy.
*/
String toVerboseString();
/**
* Asserts (using java assertions) that the provided allocator is currently open. If assertions
* are disabled, this is a no-op.
*/
void assertOpen();
/** Gets the rounding policy of the allocator. */
default RoundingPolicy getRoundingPolicy() {
return DefaultRoundingPolicy.DEFAULT_ROUNDING_POLICY;
}
/**
* EXPERIMENTAL: Wrap an allocation created outside this BufferAllocator.
*
* <p>This is useful to integrate allocations from native code into the same memory management
* framework as Java-allocated buffers, presenting users a consistent API. The created buffer will
* be tracked by this allocator and can be transferred like Java-allocated buffers.
*
* <p>The underlying allocation will be closed when all references to the buffer are released. If
* this method throws, the underlying allocation will also be closed.
*
* @param allocation The underlying allocation.
*/
default ArrowBuf wrapForeignAllocation(ForeignAllocation allocation) {
throw new UnsupportedOperationException();
}
}